天天看點

數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

一、聚類

1、聚類:屬于無監督學習,物以類聚人以群分。

2、監督學習:有Y

3、無監督學習:無y,聚類屬于無監督學習,即訓練集資料是不含有标簽的,聚類的目的是根據樣本資料内部的特征,将資料分為若幹個類别,每個類别就是一個簇,結果使得簇内的資料相似度大,不同簇内的資料相似度小。其樣本的相似性是根據距離來度量的。

4、聚類算法步驟:

數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

5、優化目标:

數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

要使得每一個簇,以及簇内的所有點距離質心的距離最小,用SSE來衡量。

6、怎樣判斷某個模型的SSE大于另外一個模型:不僅需要保證樣本數量相同,同時還需要簇的數量也相同,在滿足這兩個條件下,在使用SSE來判斷模型效果才有意義。

7、算法的優缺點:

數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

8、聚類的使用場景:

  • 商業群體,産品定位,商品推薦;
  • 對相似的文檔内容進行劃分;
  • 社交網絡自動識别推薦人際圈,互相引薦;
  • 資料處理對資料異常值進行檢測;

二、程式實作

1、首先來繪制一下學生的散點圖:

import numpy as np 
import matplotlib.pyplot  as plt 
plt.rcParams["font.family"]="SimHei"
plt.rcParams["axes.unicode_minus"]=False
plt.rcParams["font.size"]=12 

np.random.seed(1)
x=np.random.randint(70,100,size=(50,2))
plt.scatter(x[:,0],x[:,1])
plt.xlabel("國文")
plt.ylabel("數學")
           

輸出:Text(0, 0.5, ‘數學’)

數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

2、訓練:使用sklearn中的kmeans進行均值聚類,當完成訓練後可以通過KMEANS來獲得相關屬性值。

from sklearn.cluster import KMeans
kmeans=KMeans(n_clusters=4)#n是簇的數量
kmeans.fit(x)
#擷取聚類後的質心
print("質心:",kmeans.cluster_centers_)
#擷取每個樣本所屬的簇,标簽的數值對應所屬簇的索引
print("标簽:",kmeans.labels_)
#擷取SSE,也叫簇慣性
print("SSE:",kmeans.inertia_)
#擷取疊代次數
print("疊代次數:",kmeans.n_iter_)
#聚類的分值,分值越大,效果越好,直接取SSE的相反數
print("分值:",kmeans.score(x))

輸出:
質心: 
 [[91.        77.58333333]
 [93.16666667 89.83333333]
 [75.4        78.33333333]
 [77.45454545 94.27272727]]
标簽: [2 2 2 2 2 2 2 0 1 0 1 3 3 1 0 1 3 0 0 2 3 1 2 1 3 3 0 0 2 3 1 2 1 2 1 0 0 1 2 1 3 3 0 0 2 1 3 3 0 2]
SSE: 1582.0924242424242
疊代次數: 7
分值: -1582.092424242399
           

3、預測:對訓練集之外的樣本進行預測,KMeans的算法的預測很簡單,就是看預測樣本與哪個質心的距離最近,就将其測為那個類别。

#預測
unknown=np.array([[76,99],[94,80]])
y_hat=kmeans.predict(unknown)
print(y_hat)

輸出:
[3 0]
           

可以看到前一個樣本屬于第三個簇,而第二個樣本屬于第二個簇。

4、繪制圖形,實作可視化

def plot_cluster(model,train,test=None):
    color=np.array(["r","g","b","orange"])
    cc=model.cluster_centers_
    label=model.labels_
    plt.scatter(cc[:,0],cc[:,1],marker="+",s=150,c=color)
    plt.scatter(train[:,0],train[:,1],c=color[label])
    if test is not None:
        y_hat=model.predict(test)        plt.scatter(test[:,0],test[:,1],marker="*",s=150,c=color[y_hat])
        plt.xlabel("國文")
        plt.ylabel("數學")
        plt.title(f"SSE:{model.inertia_:.2f}疊代次數:{model.n_iter_}")
plot_cluster(kmeans,x,unknown)
           

輸出:

數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

5、初始質心的影響:

#初始質心的影響
seed=[10,17]
plt.figure(figsize=(15,5))
for i in range(1,3):
    plt.subplot(1,2,i)
    kmeans=KMeans(n_clusters=4,init="random",n_init=1,random_state=seed[i-1])
    kmeans.fit(x)
    plot_cluster(kmeans,x)   
           
數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

改進:随機初始化多組質心,執行多次,然後選擇SSE最小的初始化質心。把之前的n_init=1改成n_init=10

plt.figure(figsize=(15,5))
for i in range(1,3):
    plt.subplot(1,2,i)    
    kmeans=KMeans(n_clusters=4,init="random",n_init=10,random_state=seed[i-1])
    kmeans.fit(x)
    plot_cluster(kmeans,x)
           
數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

三、各種算法對比

1.KMeans++

數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

基于機率性的選擇。傾向于選擇距離目前質心較遠的樣本作為下一個質心。

kmeans=KMeans(n_clusters=4,init="k-means++")
kmeans.fit(x)
plot_cluster(kmeans,x)
           
數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

2.Mini Batch K-Means

1、概述和算法步驟

數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

2、程式實作:

import time
import pandas as pd
from sklearn.cluster import MiniBatchKMeans, KMeans
from sklearn.metrics.pairwise import pairwise_distances_argmin 
from sklearn.datasets import make_blobs

centers = [[1, 1], [-1, -1], [1, -1]] # 生成用于聚類的資料。
# n_samples:樣本數量。
# n_features:特征數量。
# centers:聚類中心。
# cluster_std:簇的标準差。可以統一指定,也可以為每個簇指定不同的标準差。
# random_state:随機種子,用來生成樣本資料。
X, y = make_blobs(n_samples=3000, n_features=2, centers=centers,cluster_std=0.7, random_state=0)
colors = np.array(["red", 'green', 'blue']) 
plt.scatter(X[:, 0], X[:, 1], c=colors[y], marker=".")
           
數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

對比一下KMeans與Mini Batch k-means++的效果:

# 定義函數,用于計算模型訓練時間。 
def elapsed_time(model, data):
    start = time.time() 
    model.fit(data) 
    end = time.time() 
    return end - start
n_clusters = len(centers)
kmeans = KMeans(init='k-means++', n_clusters=n_clusters, n_init=10) 
mbk = MiniBatchKMeans(init='k-means++', n_clusters=n_clusters,batch_size=100, n_init=10)
kmeans_time = elapsed_time(kmeans, X)
mbk_time = elapsed_time(mbk, X) 
print("K-Means消耗時間:", kmeans_time)
print("Mini Batch K-Means消耗時間:", mbk_time) 
print("K-Means SSE:", kmeans.inertia_ )
print("Mini Batch K-Means SSE:", mbk.inertia_ ) 
print("K-Means的質心:", kmeans.cluster_centers_) 
print("Mini Batch K-Means的質心:", mbk.cluster_centers_)
輸出:
K-Means消耗時間: 0.2605900764465332
Mini Batch K-Means消耗時間: 0.16374659538269043
K-Means SSE: 2470.583458090532
Mini Batch K-Means SSE: 2474.8568874307243
K-Means的質心: [[ 1.07705469 -1.06730994]
 [-1.07094261 -1.00512907]
 [ 0.96835544  1.01900336]]
Mini Batch K-Means的質心: [[ 0.95075134  1.07067177]
 [-1.03843646 -0.9962812 ]
 [ 1.11699156 -1.08205516]]
           

3.如何确定合适的k值

使用肘部法則:

sse=[]
scope=range(1,10)
for k in scope:
    kmeans=KMeans(n_clusters=k)
    kmeans.fit(x)
    sse.append(kmeans.inertia_)
plt.xticks(scope)
plt.plot(scope,sse,marker="o")
    
           
數理統計——Kmeans一、聚類二、程式實作三、各種算法對比1.KMeans++2.Mini Batch K-Means3.如何确定合适的k值

是以使用肘部法則,選擇k=3。