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

5、優化目标:
要使得每一個簇,以及簇内的所有點距離質心的距離最小,用SSE來衡量。
6、怎樣判斷某個模型的SSE大于另外一個模型:不僅需要保證樣本數量相同,同時還需要簇的數量也相同,在滿足這兩個條件下,在使用SSE來判斷模型效果才有意義。
7、算法的優缺點:
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, ‘數學’)
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)
輸出:
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)
改進:随機初始化多組質心,執行多次,然後選擇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)
三、各種算法對比
1.KMeans++
基于機率性的選擇。傾向于選擇距離目前質心較遠的樣本作為下一個質心。
kmeans=KMeans(n_clusters=4,init="k-means++")
kmeans.fit(x)
plot_cluster(kmeans,x)
2.Mini Batch K-Means
1、概述和算法步驟
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與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")
是以使用肘部法則,選擇k=3。