目錄算法
1.聚類概念app
2.類似度或距離度量dom
2.1 閔可夫斯基距離(Minkowski distance)機器學習
2.2 歐式距離(Euclidean distance)ide
2.3 曼哈頓距離(Manhattan distance)函數
2.4 馬哈拉諾比斯距離(Mahalanobis distance)學習
2.5 相關係數測試
2.6 夾角餘弦優化
2.7 度量方式idea
1.聚類概念
聚類是指:把給定樣本,依據它們之間的距離或類似度,劃分爲若干個「類」或「簇」。使得類似度較高的樣本彙集在同一個類,不類似的樣本分散在不一樣的類。
聚類屬於無監督學習,方法不少,最經常使用的是:層次聚類、K均值聚類(Kmeans)、模糊聚類(模糊Cmeans)。在聚類中十分重要的概念就是距離或者類似度度量。
2.類似度或距離度量
聚類的輸入是樣本數據,每一個樣本又由m個屬性的特徵組成,因此輸入能夠定義爲,其中,行數是維度的個數,列數是樣本的個數。在計算距離或類似度的時候,有多種方法,通常是距離、相關係數夾角餘弦。一般狀況下:
距離越小,類似度越高;距離越大,類似度越低。
相關係數越接近1,類似度越高;相關係數越接近0,類似度越低。
夾角餘弦越接近1,類似度越高;夾角餘弦越接近0,類似度越低。
2.1 閔可夫斯基距離(Minkowski distance)
,其中()
2.2 歐式距離(Euclidean distance)
當p=2的時候,即爲歐式距離:
2.3 曼哈頓距離(Manhattan distance)
當p=1的時候,即爲曼哈頓距離:
2.4 馬哈拉諾比斯距離(Mahalanobis distance)
馬哈拉諾比斯距離簡稱爲馬氏距離,考慮各個份量之間的相關性與各個份量的尺度相關性。馬氏距離越大,則類似度越小;馬氏距離越小,則類似度越大。
定義輸入樣本的協方差矩陣爲,則樣本與的馬氏距離爲:,其中即第i列特徵值,,即第j列特徵值。
2.5 相關係數
樣本之間的類似度除了用距離度量外,還可使用相關係數(correlation coefficient)來表示。與距離度量不一樣,相關係數越接近1,則表示樣本越類似;相關係數越接近於0,表示樣本越不類似。
通常和的相關係數定義爲:,其中,
2.6 夾角餘弦
樣本之間的類似度還能夠用夾角餘弦表示,夾角餘弦值越接近1,表示樣本越類似;夾角預餘弦值越接近0,表示樣本越不類似。
夾角餘弦能夠定位爲:
2.7 度量方式
不一樣度量方式獲得的結果不必定一致,具體採用哪一種度量方式,須要結合本身實際狀況出發。例以下圖
從距離上看,A與B的距離更近,所以A和B比A和C更類似;從夾角餘弦上看,A和C比A和B更類似。
3. 類或簇的基本概念
經過聚類,能夠獲得類或簇,它是輸入樣本的子集。瞭解距離和類似度量的方式後,就須要瞭解聚類中經常使用的一些概念,這樣在後續的計算中,可以不使得概念混淆。
3.1 聚類分類
硬聚類:假定一個樣本智能屬於一個類,或類的交集爲空集,這種聚類屬於硬聚類。本文中的層次聚類、K均值聚類和模糊聚類屬於硬聚類。
軟聚類:若是一個樣本能夠屬於多個類,或類的交集不爲空集,那麼這種方法稱爲軟聚類。
3.2 類或簇
用表示類或簇,,表示勒種的樣本,表示中樣本的個數。表示,的距離。
哪怎樣算是一個類或簇?
給定一個正數,若,則能夠稱爲一個類或簇
給定一個正數,若,能夠稱爲一個類或簇
給定一個正數,若能夠稱爲一個類或簇
因此,當某個集合中內,任意樣本之間距離小於等於給定的正數,那麼就能夠認爲這個集合是一個類或簇。
3.3 類的中心
類的中心指的就是類的均值,定義爲:
3.4 類的直徑
類的直徑是指任意兩個樣本之間最大的距離,定義爲:
3.5 類的散佈矩陣
定義爲:,衡量類中樣本的分散狀況,相似方差。
3.6 類的協方差
定義爲:,衡量樣本之間的相關性。
3.7 類之間最短距離或單鏈接
類與類樣本之間的最短距離定義爲兩個類之間的最短距離:
3.8 類之間最長距離或徹底鏈接
類與類樣本之間的最短距離定義爲兩個類之間的最短距離:
3.9 中心距離
類與類的類中心和之間的距離爲兩個類之間的中心距離:
3.10 平均距離
類與類的任意兩個樣本之間的平均距離爲兩個類之間的平均距離:
4 層次聚類
瞭解聚類的距離和類似度以及基礎概念,就能夠開始進行聚類分析。
所謂層次聚類,是指按照層次的方法找類之間的層次關係,有層次聚合(自下而上)、層次分裂(自上而下)兩種方法。
以下圖,層次聚合是指,初始的時候,每一個樣本單獨屬於一個類,而後按照類之間距離最小合併的原則,迭代合併類,直至合併到指定類的個數,或者只有1個類。層次分裂聚類與層次聚合相反,咱們僅介紹聚合聚類。
4.1 層次聚合
輸入:n個樣本組成的樣本集合
輸出:對的一個層次化聚類
4.2 算法流程:
- 計算n個樣本兩兩之間的歐式距離,記作距離矩陣;
- 構造n個類,每個類只包含一個樣本;
- 合併類間距離最小的兩個類,構建一個新的類;
- 計算新的類與當前各種的距離。若類的個數爲1,或者指定個數,則終止計算;不然回到3
4.3 案例
隨機生成100個二維數據,按照層次聚類進行聚類。當K=4的時候,獲得的聚類效果以下。
這100個樣本的類標籤:cluster labels:[1 0 0 1 3 0 0 3 0 0 1 0 0 0 0 0 0 0 0 0 0 1 3 0 1 3 1 0 0 0 3 0 0 0 3 0 2 0 1 1 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0]
代碼以下:
import numpy as np import matplotlib.pyplot as plt from scipy.spatial.distance import pdist from scipy.cluster.hierarchy import linkage from scipy.cluster.hierarchy import dendrogram from sklearn.cluster import AgglomerativeClustering colo = ['b', 'g', 'r', 'c', 'm', 'y', 'k'] # x = np.random.randint(0, 10, [100, 2]) x = 10 * np.random.rand(100, 2) shape = x.shape K = 4 # 簇個數 # 分析層次聚類 row_clusters = linkage(pdist(x, metric='canberra'), method='complete') ''' pdist:計算樣本距離,其中參數metric表明樣本距離計算方法 (euclidean:歐式距離、minkowski:明氏距離、chebyshev:切比雪夫距離、canberra:堪培拉距離) linkage:聚類,其中參數method表明簇間類似度計算方法 (single: MIN、ward:沃德方差最小化、average:UPGMA、complete:MAX) ''' row_dendr = dendrogram(row_clusters) plt.tight_layout() plt.title('canberra-complete') plt.show() # 層次聚類 clf = AgglomerativeClustering(n_clusters=K, affinity='canberra', linkage='complete') labels = clf.fit_predict(x) print('cluster labels:%s' % labels) for k, col in zip(range(0, K), colo): X = labels == k plt.plot(x[X, 0], x[X, -1], col + 'o') plt.xlabel('x') plt.ylabel('y') plt.title('hierarchical_clustering') plt.show()
5. K均值聚類(Kmeans)
K均值聚類是最經常使用的聚類方法,這是一種基於集合劃分的聚類算法。
K均值聚類把樣本集合劃分爲k個子集,構成k個類,將n個樣本分配到k個類中,每一個樣本到所屬類的中心距離最小。
5.1 K均值的聚類策略
k均值聚類是經過最小化損失函數選取最優的劃分或函數,即採用歐式距離做爲樣本之間的距離度量,而後定義樣本與述所類的中心的距離總和損失函數:,其中表明聚類的中心。因此K均值聚類就是最優化的問題,在實現中,解決這類
問題的方法是經過迭代方法求解。
5.2 算法流程
輸入:n個樣本的集合
輸出:樣本的聚類
- 初始化,令t=0,隨機選擇k個樣本做爲初始類中心;
- 樣本聚類:計算每一個樣本到每一個類中心的距離,將每一個樣本指派到與其最近的類,構成聚類結果;
- 計算新的類中心:對聚類結果,計算類中全部樣本的均值,做爲新的聚類中心;
- 若是迭代收斂,或者符合中止條件,輸出;不然,令t=t+1,返回第2步。
5.3 實際案例
利用k均值聚算法求5個樣本的二維數據集合
5.4 Kmeans的k值選擇
K均值的類別數,一般狀況下是人爲指定的。在實際應用應用中,每每不知道K取多少是最合適,所以一般是使用嘗試的方法,即令k=2到x(x本身設定,少於樣本個數的一半便可)。可使用手肘法選擇k值,即經過每一個k值下的均方差曲線的手肘點做爲最優的k值。也能夠選擇使用輪廓係數法做爲依據,選擇使輪廓最大的值對應的k值爲最優k值。
5.5 程序
下面程序實現的是,隨機選擇100個二維樣本,對其進行聚類,k值的從2依次遞增到7。
下圖是k取不一樣值時候的均方偏差曲線,從圖中能夠看出,手肘點在k=4的時候。要是以此爲選擇依據的話,K=4時有最優的聚類結果
下圖是輪廓係數法求出的值,能夠看出,當K=4的時候,輪廓係數最大。若以輪廓係數爲選擇依據,那麼K=4的時候有最優的聚類結果。
代碼以下:
import numpy as np from sklearn.cluster import KMeans from sklearn.metrics import silhouette_score import matplotlib.pyplot as plt # colo = [[0, 0, 255], [0, 255, 0], [255, 0, 0], [0, 255, 255], [255, 255, 0], [255, 0, 255], [255, 255, 255]] colo = ['b', 'g', 'r', 'c', 'm', 'y', 'k'] # x = np.random.randint(0, 10, [100, 2]) x = 10 * np.random.rand(100, 2) shape = x.shape sse = [] score = [] K = 8 for k in range(2, K): clf = KMeans(n_clusters=k) clf.fit(x) sse.append(clf.inertia_) lab = clf.fit_predict(x) score.append(silhouette_score(x, clf.labels_, metric='euclidean')) for i in range(shape[0]): plt.xlabel('x') plt.ylabel('y') plt.title('k=' + str(k)) plt.plot(x[i, 0], x[i, -1], colo[lab[i]] + 'o') plt.show() X = range(2, K) plt.xlabel('k') plt.ylabel('sse') plt.title('sum of the squared errors') plt.plot(X, sse, 'o-', ) plt.show() plt.xlabel('k') plt.ylabel('Score') plt.title('Silhouette Coefficient') plt.plot(X, score, 'o-', ) plt.show()
5.6 K均值聚類特性
- K均值聚類每每是事先指定k值,以歐式距離做爲衡量樣本距離的方法。以樣本到所屬類中心距離總和做爲目標函數。算法是使用迭代計算,每每不能獲得全局最優。
- K均值聚類屬於啓發式方法,初始中心的選擇會直接影響到聚類的結果。
- K均值聚類如何選擇K,一般須要嘗試不一樣的k值,經過手肘法或者輪廓係數法肯定最優k值。
6. 模糊聚類(FCM/模糊Cmeans)
模糊聚類是指模糊C均值聚類(Fuzzy Cmeans),簡寫爲FCM或者模糊Cmeans,同Kmeans同樣,是一種被普遍應用的聚類算法。經過測試,發現,模糊Cmeans的聚類效果比Kmeans要優秀。
模糊聚類引入一個隸屬度矩陣,它是衡量當前樣本屬於某個類的可能性大小。當前樣本可能屬於類1,也可能屬於累2,所以這種聚類成爲模糊聚類。
若數據集被劃分紅c個類,那麼有c個類中心,樣本與類中心的隸屬度爲,因而就有約束函數:
,其中m是隸屬度因子。
接下來就是利用約束函數求解和,採用的拉格朗日乘數法(具體推導,點擊:聚類之詳解FCM算法原理及應用,這裏就不作詳細介紹),獲得和是相互關聯的。在算法開始的時候,假設其中一個值(例如),經過迭代計算,和經過對方得計算本身。
能夠簡單是樣本屬於摸個類的可能性大小,是樣本與貢獻度乘積的結果。
6.1 算法流程
輸入:樣本,類的個數c,隸屬度因子m(通常取2),迭代次數
輸出:模糊Cmeans聚類結果
- 肯定分類個數c,指數m的值,肯定迭代次數(這是結束的條件,固然結束的條件能夠有多種)。
- 初始化一個隸屬度(和爲1);
- 根據計算聚類中心;
- 這個時候能夠計算目標函數了
- 根據返回去計算,回到步驟3,一直循環直到結束。
6.2 案例
隨機取100個二維樣本,分類樣本個數爲4,隸屬度因子爲2.
獲得分類結果:cluster labels:[1 2 2 2 2 0 1 1 0 2 2 2 1 0 0 1 2 3 2 3 1 0 1 2 0 2 1 2 1 0 1 0 0 1 1 3 0 3 2 0 0 0 2 1 0 1 3 1 0 2 0 0 1 3 1 2 1 1 0 0 0 3 3 0 3 3 3 1 3 0 0 0 3 1 1 0 2 3 2 2 1 3 1 0 2 0 1 3 1 1 1 1 2 0 1 1 1 0 1 3]
代碼:
import numpy as np import matplotlib.pyplot as plt colo = ['b', 'g', 'r', 'c', 'm', 'y', 'k'] # x = np.random.randint(0, 10, [100, 2]) x = 10 * np.random.rand(100, 2) shape = x.shape K = 4 # 簇個數 def FCM(X, c_clusters=3, m=2, eps=10): membership_mat = np.random.random((len(X), c_clusters)) membership_mat = np.divide(membership_mat, np.sum(membership_mat, axis=1)[:, np.newaxis]) while True: working_membership_mat = membership_mat ** m Centroids = np.divide(np.dot(working_membership_mat.T, X), np.sum(working_membership_mat.T, axis=1)[:, np.newaxis]) n_c_distance_mat = np.zeros((len(X), c_clusters)) for i, x in enumerate(X): for j, c in enumerate(Centroids): n_c_distance_mat[i][j] = np.linalg.norm(x - c, 2) new_membership_mat = np.zeros((len(X), c_clusters)) for i, x in enumerate(X): for j, c in enumerate(Centroids): new_membership_mat[i][j] = 1. / np.sum((n_c_distance_mat[i][j] / n_c_distance_mat[i]) ** (2 / (m - 1))) if np.sum(abs(new_membership_mat - membership_mat)) < eps: break membership_mat = new_membership_mat return np.argmax(new_membership_mat, axis=1) labels = FCM(x, c_clusters=K, m=2, eps=10) print('cluster labels:%s' % labels) for k, col in zip(range(0, K), colo): X = labels == k plt.plot(x[X, 0], x[X, -1], col + 'o') plt.xlabel('x') plt.ylabel('y') plt.title('FCM') plt.show()
下面是使用機器學習庫實現的模糊Cmeans算法,能夠直觀看出,在聚類效果上要比Kmeans要優秀些。
代碼:
import numpy as np from skfuzzy.cluster import cmeans from sklearn.metrics import silhouette_score import matplotlib.pyplot as plt # colo = [[0, 0, 255], [0, 255, 0], [255, 0, 0], [0, 255, 255], [255, 255, 0], [255, 0, 255], [255, 255, 255]] colo = ['b', 'g', 'r', 'c', 'm', 'y', 'k'] # x = np.random.randint(0, 10, [100, 2]) x = 10 * np.random.rand(100, 2) shape = x.shape FPC = [] K = 8 labels = [] for k in range(2, K): center, u, u0, d, jm, p, fpc = cmeans(x.T, m=2, c=k, error=0.5, maxiter=10000) ''' 注意輸入數據是kemans數據的轉置 center是聚類中心、u是最終的隸屬度矩陣、u0是初始化隸屬度矩陣 d是每一個數據到各個中心的歐式距離矩陣,jm是目標函數優化、p是迭代次數 fpc是評價指標,0最差,1最好 ''' label = np.argmax(u, axis=0) for i in range(shape[0]): plt.xlabel('x') plt.ylabel('y') plt.title('c=' + str(k)) plt.plot(x[i, 0], x[i, -1], colo[label[i]] + 'o') plt.show() print('%d c\'s FPC is:%0.2f' % (k, fpc)) FPC.append(fpc) X = range(2, K) plt.xlabel('c') plt.ylabel('FPC') plt.title('FCM-cmeans') plt.plot(X, FPC, 'o-', ) plt.show()
注意skfuzzy.cluster的安裝方法pip install -U scikit-fuzzy