ml課程:聚類概述及K-means講解(含程式碼實現)
阿新 • • 發佈:2018-11-25
以下是我的學習筆記,以及總結,如有錯誤之處請不吝賜教。
本文主要介紹聚類以及K均值演算法的推倒過程,最後有相關程式碼案例。
說到聚類就不得不先說說機器學習的分類。
機器學習主要分為三類:
監督學習:分類、迴歸...
無監督學習:聚類、降維...
強化學習。
下面這張圖是機器學習python庫sklearn的一個分類:
聚類的作用主要分為三個:
- 組織資料
- 降維
- 資料預處理,為下部資料的處理做準備
聚類的應用主要包括:
- 網頁搜尋
- 生物技術
- 社交網路(如facebook、twitter等等)
- 商品推薦系統(劃重點)
- 天文
- 等等
輸入:兩個點之間的距離d(x)
輸出:資料類別歸屬
聚類基本的三類演算法:
下面重點說K-means。
目標函式:最小化點到中心點的距離平方。公式如下:
時間複雜度:屬於NP hard(在非確定圖靈機上無法解決(量子計算機))
先看幾個特例:
- K=1時的演算法:
- d=1時:需要用到動態規劃來計算。
K-means實現常用的幾種演算法:
- 通用的The Lloyd‘s演算法,即通過兩個迭代迴圈,第一層迴圈:求得到中心點的距離最近的點,第二層迴圈:求點到中心點的均值,不斷迴圈迭代。
但是對於這種演算法,初始點的選擇是需要重點考慮的,初始化的方法主要有以下幾點:
- 隨機初始化,即隨機挑選點:
最後聚類得到:
但是容易遇到這種問題:
我們假設資料分佈是隨機獨立分佈,那麼所有資料被分到正確的類的概率為:,約等於:,概率隨著k的增大呈指數級別減小。
- 最遠點初始化,即找到距離前一個點最遠點作為初始化點:
但是最遠點也有問題:
- D2sampling:是目前最好的初始化方法,即加權重的最遠點
最關鍵的是,這個演算法的時間複雜度並沒有增加為:線性O(nkd),其中n為資料點個數,k為聚類中心點個數,d為資料集的維度。即初始化的複雜度可以忽略。
下面說說如何選擇k值:
- cross_validation 將資料集分為訓練集和測試集,選擇在訓練集效果最好的k值即可。
- elbow's method 找到k值下降斜率的拐點。
- 層次聚類,是聚類的另一個方法,他的不同類別有不同層次,類似於樹狀。他主要分為以下兩類:
- 自上而下
- 自下而上
自下而上有三種計算兩個類距離的方法:
- single linkage
- complete linkage
- average linkage
這個演算法的時間複雜度較高,為:O(n3),當然通過優先佇列的資料結構可以降到O(n2logn)。
最重點的來了,K-means程式碼實現如下:
import os, sys
import argparse
import numpy as np
import time
# Vanilla K-means clustering.
samples = np.vstack([samples1, samples2, samples3])
rorder = np.arange(num_pts * 3)
rorder = np.random.shuffle(rorder)
samples = samples[rorder, :].squeeze()
# Lloyd's algorithm, with random initialization.
k = 3
centers = np.random.rand(k, 2)
num_iters = 10
losses = []
# Save for repeated use.
xdist = np.sum(samples * samples, axis=1)
for _ in xrange(num_iters):
# Compute distance to each center.
cdist = np.sum(centers * centers, axis=1)
consts = xdist[:, np.newaxis] + cdist
dists = consts - 2 * np.dot(samples, centers.T) #計算到中心點距離
# Compute cluster assignment.
ids = np.argmin(dists, axis=1) #新的中心點迭代
losses.append(np.sum(np.min(dists, axis=1)))
for i in xrange(k):
centers[i, :] = np.mean(samples[ids == i], axis=0)
具體可以看這裡:歡迎關注我的github
未完,待續。