1、聚類任務
我們知道在無監督學習中,訓練樣本的標籤是未知的,所以爲了能夠通過這些無標籤的訓練樣本來探究數據的內在性質及其規律,便產生了許多無監督學習算法。
其中,我們若想要通過數據的內在性質來分類數據,那麼出現了一種叫 “聚類” 的方法。
【 定義 】
聚類針對給定的樣本,依據它們特徵的相似度或距離,將其歸併到若干個 “類” 或 “簇” 的數據分析問題。而這些類或簇通常是不相交的子集。而聚類過程得到的子集是沒有其本就存在的概念語義的,它需要由使用者來把握和命名。
【 符號化 】
假定樣本集 包含 個無標記樣本,每個樣本 是一個 維特徵向量。
通過聚類算法,樣本集被劃分成 個不相交的簇 ,其中 且
而樣本 的 “簇標記” 用 表示。
聚類結果可用 表示。
2、性能度量
因爲樣本是沒有標籤的,所以我們最終通過程序自動實現聚類的結果到底是好還是壞,我們需要一個標準或者指標去度量的。而聚類性能度量稱爲 “有效性指標”。除了評估聚類結果好壞,若明確了最終要使用的性能度量,則可以直接將其作爲聚類過程的優化目標,從而更好找到更優的聚類結果。
很自然的,如果我們希望聚類結果更好,那麼我們其實就希望最終是 “物以類聚” 的情況,即同一類中的樣本距離足夠近,而不同類之間的樣本距離足夠的遠。 以術語來描述就是,聚類結果 “簇內相似度” 高 且 “簇間相似度” 低。
而聚類性能度量大致有兩類:
- 外部指標:將聚類結果與某個“參考模型”進行比較。
- 內部指標:直接考察聚類結果而不利於任何參考模型。
在西瓜書中,有如下公式作爲性能指標符號:
基於上面4式可以得到一些常用的聚類性能度量外部指標:
顯然,上述性能度量的結果值均在 區間,值越大越好。
3 距離或相似度
首先定義樣本集合,它可用矩陣 表示,矩陣第 行表示第 個樣本,第 列表示第 個屬性:
聚類的核心就是相似度或距離,我們主要使用如下距離或相似度:
3.1 閔可夫斯基距離 (Minkowski distance)
【定義】
給定樣本 ,則兩個樣本間的閔可夫斯基距離定義爲:
當 ,則稱爲 歐氏距離 (Euclidean distance) ,即
當 ,則稱爲 曼哈頓距離 (Manhattan distance) ,即
當 ,則稱爲 切比雪夫距離 (Chebyshev distance) ,即取各個座標數值差的絕對值的最大值
閔可夫斯基距離越大相似度越小,距離越小相似度越大
3.2 馬哈拉諾比斯距離 (Mahalanobis distance)
簡稱 馬氏距離,也是另一種常用相似度,考慮各個分量之間的相關性並與各個分量的尺度無關。
【定義】
給定一個樣本集合 ,其協方差矩陣記爲 。樣本 與 之間的馬哈拉諾比斯距離定義爲:
當 爲單位矩陣時,馬氏距離就是歐氏距離。
同樣,馬哈拉諾比斯距離越大相似度越小,距離越小相似度越大
3.3 VDM—無序屬性
先來理解一下什麼是有序屬性和無序屬性。
舉個例子:一個定義域爲,這樣的離散屬性可直接計算距離,很明顯"1" 與 “2” 比與 “3” 更加接近,它便稱爲 “有序屬性”。可以理解,閔可夫斯基距離可用於計算這種有序屬性。
而若定義域爲 { 飛機,火車,輪船 },這樣的離散屬性則不能直接計算距離,稱爲 “無序屬性”。
那麼對於無序屬性,便可以採用 VDM 方法來計算。
【定義】
3.4 相關係數
樣本之間相似度可以使用 相關係數(correlation coefficient) 來表示。因爲是表示相關性的指標,所以其值越大則越相似,值越小則越不相似,具體地,係數的絕對值越接近於1,樣本相似度越大;越接近於0,樣本相似度越小。
【定義】
樣本 與 之間的相關係數定義爲:
其中,
在python中代碼爲:
## 求皮爾森相關係數
def corrcoef(x, y):
sum1 = np.sum(x)
sum2 = np.sum(y)
sumofxy = np.sum(x * y)
sumofx2 = np.sum(x * x)
sumofy2 = np.sum(y * y)
num = sumofxy - (np.float(sum1) * np.float(sum2) / x.shape[0])
den = np.sqrt((sumofx2 - np.float(sum1 ** 2) / x.shape[0]) * (sumofy2 - np.float(sum2 ** 2) / x.shape[0]))
return num/den
3.5 夾角餘弦
樣本之間相似度可以使用 夾角餘弦 來表示。夾角餘弦越接近於1,樣本相似度越大;越接近於0,樣本相似度越小。
【定義】
樣本 與 之間的夾角餘弦定義爲:
在python中代碼爲:
## 求夾角餘弦
def cosVector(x, y):
num = sum(map(float, x*y))
den = np.linalg.norm(x) * np.linalg.norm(y)
return num/float(den)