K-means屬於非監督機器學習算法,主要用於聚類分析。好比我們收集某新聞網站的新聞數據,可是在採集過程當中忘了收集新聞的新聞類別(假設一共採集了軍事、政治、文化、教育四大類),如今咱們須要對成千上萬的新聞文檔進行分類,這時候咱們可使用k=4的簇數(聚類數)對新聞數據施行Kmeans算法,並對每篇文檔進行標註。算法
可是咱們仍是要強調一點,K-means是無監督學習,雖然不須要標註好的數據,可是仍是須要你對數據有必定的瞭解,可以大概猜想出k值(簇的數目)的範圍。這樣Kmeans算法才能開始更準確合理的學習數據中的類規律,並做出較好的分類。(其實還有分類算法的,這裏我用分類吧,不太嚴謹哈。)數組
K-means原理
K-means,從字面看含有k和means兩部分。K-means算法會將樣本量N特徵數m的數據X (其中X是N*m的矩陣)分到K個簇中,每一個簇會有一個重心centroids。dom
聚類效果的目標是經過計算簇中各個點到重心的距離平方和Inetia儘量的小。Inetia計算公式以下機器學習
C是一個簇;u是簇C的重心;Xj是簇C中的任意點。ide
Inetia也有個問題,Inetia不是正規的度量方式;咱們僅僅知道Inetia越小越好,0是最優狀態。可是極端的狀況下,若是有n條數據,咱們將其分紅n類,Inetia會等於0。函數
K-means算法:
K-means算法比較出名的的易於理解的是LIoyd算法,包含三個步驟:學習
1 、從數據集X中隨機抽選k個樣本點測試
二、按照距離最近原則,將剩餘的點分派給k個簇。而上一步抽選的k個樣本點就是k個簇的重心centorid。優化
三、根據每一個簇全部的點求出新的重心centroid,並重復步驟2和步驟3。直到重心沒什麼顯著變化,聚類結束。網站
優化K-means算法
充足運行時間條件下,K-means總能最終收斂,可是每每是局部最優。
聚類的表現高度依賴於重心centroid的最初的選擇。因此K-means每每須要運行好幾回,這裏也就是max_iter參數的意義,一次隨機抽選centroid偏差較大,因此運行max_iter次,最終選擇表現最好的做爲最終聚類結果。
解決隨機抽選centroid重心,有一種「k-means++」初始化方法,scikit-learn已經實現(經過使用init=k-means參數)。這種初始化選擇重心centroid的方法,儘可能保證k個重心彼此之間的距離儘量的遠,這樣比隨機抽選centroid更好。
K-means中海油一個n_job參數,能夠加快模型學習速度。當n_job=-1時,電腦使用所有的處理器進行並行運算。可是並行運算雖然會提升運行速度,卻以消耗大量內存爲代價。
案例
這個例子是爲了說明k-means會產生不直觀和可能意想不到的簇的狀況。
在前三幅圖中,輸入數據不符合一些隱含假設,使得k-means產生了不須要的聚類。最後一個圖,雖然各個簇的樣本量分佈不均衡,可是從咱們直覺仍是能看出聚類的合理性。
import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans from sklearn.datasets import make_blobs #畫圖,設置畫布尺寸 plt.figure(figsize=(12, 12)) #隨機生成1500個樣本點 n_samples = 1500 #保證下次隨機生成的數據與前一次生成的數據是相同的 random_state = 170 #給k-means算法生成測試數據的函數 X, y = make_blobs(n_samples=n_samples, random_state=random_state) #咱們看看前10條數據 print(X[:10], y[:10])
make_blob生成n_samples*n_features特徵矩陣X和標籤y,X矩陣默認特徵數n_features=2。因此咱們如今獲取的特徵矩陣是1500行2列。而標籤y是一維數組。
如今咱們看看前10條數據。
[[ -5.19811282 0.64186932] [ -5.75229538 0.41862711] [-10.84489837 -7.55352273] [ -4.57098483 -0.80101741] [ -3.51916215 0.0393449 ] [ 1.60391611 0.76388041] [ -9.75157357 -5.2030262 ] [-11.51023635 -4.16284321] [ -7.72675795 -5.86656563] [ 2.67656739 3.29872756]] [1 1 0 1 1 2 0 0 0 2] ``
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
#畫圖,設置畫布尺寸
plt.figure(figsize=(12, 12))
#隨機生成1500個點(二維點)
n_samples = 1500
#記錄狀態,能夠保證下次隨機生成的數據與前一次生成的數據是相同的
random_state = 170
#make_blob主要是給k-means算法生成測試數據的函數。這裏同時獲得特徵矩陣X和標籤label
X, label = make_blobs(n_samples=n_samples, random_state=random_state)
#我也不知道有幾類,隨便將k=2去試試吧。讓K-means學習X,並生成預測的標籤
label_pred = KMeans(n_clusters=2, random_state=random_state).fit_predict(X)
#將figure設置的畫布大小分紅幾個部分。參數‘221’表示2(row)x2(colu),即將畫布分紅2x2,兩行兩列的4塊區域。1表示我們繪製的第一幅圖
plt.subplot(221)
#X[:, 0]意思是抽取X中全部行第一列,咱們能夠理解爲座標系的x; X[:, 1]是X的第二列,咱們能夠理解爲座標系的y;再用scatter在二維座標系中繪製散點圖,顏色c使用label_pred標註。
plt.scatter(X[:, 0], X[:, 1], c=label_pred)
plt.title("k=2 cluster")
#k=3
label_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X)
plt.subplot(222)
plt.scatter(X[:, 0], X[:, 1], c=label_pred)
plt.title("k=3 cluster")
#生成不一樣類數據的,且各種的方差是存在差別的
X_varied, y_varied = make_blobs(n_samples=n_samples,cluster_std=[1.0, 2.5, 0.5],random_state=random_state)
label_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_varied)
plt.subplot(223)
plt.scatter(X_varied[:, 0], X_varied[:, 1], c=label_pred)
plt.title("k=3 Unequal Variance")
#生成不一樣類數據的,且各種樣本量不均衡#0類有500個點;1類有100點;2類僅有10個點;X_filtered = np.vstack((X[label == 0][:500], X[label == 1][:100], X[label == 2][:10]))label_pred = KMeans(n_clusters=3,random_state=random_state).fit_predict(X_filtered)plt.subplot(224)plt.scatter(X_filtered[:, 0], X_filtered[:, 1], c=label_pred)plt.title("Unevenly Sized Blobs")plt.show()