天天看點

數學模組化——K-means聚類模型Python代碼

一、簡介

K均值聚類算法是先随機選取K個對象作為初始的聚類中心。然後計算每個對象與各個種子聚類中心之間的距離,把每個對象配置設定給距離它最近的聚類中心。聚類中心以及配置設定給它們的對象就代表一個聚類。每配置設定一個樣本,聚類的聚類中心會根據聚類中現有的對象被重新計算。這個過程将不斷重複直到滿足某個終止條件。終止條件可以是沒有(或最小數目)對象被重新配置設定給不同的聚類,沒有(或最小數目)聚類中心再發生變化,誤差平方和局部最小。

二、

1.便于了解,首先建立一個明顯分為2類20*2的例子(每一列為一個變量共2個變量,每一行為一個樣本共20個樣本):

import numpy as np
c1x=np.random.uniform(0.5,1.5,(1,10))
c1y=np.random.uniform(0.5,1.5,(1,10))
c2x=np.random.uniform(3.5,4.5,(1,10))
c2y=np.random.uniform(3.5,4.5,(1,10))
x=np.hstack((c1x,c2x))
y=np.hstack((c2y,c2y))
X=np.vstack((x,y)).T
print(X)
           

結果:

[[1.4889993 4.18741329]

[0.73017615 4.07842216]

[1.15522846 4.05744838]

[1.40768457 3.76674812]

[1.376212 3.95063903]

[1.20821055 4.34138767]

[0.73898392 3.55026013]

[0.97116627 3.65432314]

[0.98267302 4.16731561]

[1.06346541 4.44383585]

[4.10945954 4.18741329]

[3.75288064 4.07842216]

[4.29638229 4.05744838]

[3.95221785 3.76674812]

[4.09826192 3.95063903]

[4.04840874 4.34138767]

[4.29594009 3.55026013]

[3.56931245 3.65432314]

[3.57962941 4.16731561]

[3.65208848 4.44383585]]

  1. 引用Python庫将樣本分為兩類(k=2),并繪制散點圖:

    #隻需将X修改即可進行其他聚類分析

import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
 
kemans=KMeans(n_clusters=2)
result=kemans.fit_predict(X) #訓練及預測
print(result)   #分類結果
 
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei'] #散點圖示簽可以顯示中文
 
x=[i[0] for i in X]
y=[i[1] for i in X]
plt.scatter(x,y,c=result,marker='o')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
           

結果:

[0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1]

  1. 如果K值未知,可采用肘部法選擇K值(假設最大分類數為9類,分别計算分類結果為1-9類的平均離差,離差的提升變化下降最抖時的值為最優聚類數K):
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from scipy.spatial.distance import cdist
 
K=range(1,10)
meanDispersions=[]
for k in K:
    kemans=KMeans(n_clusters=k)
    kemans.fit(X)
    #計算平均離差
    m_Disp=sum(np.min(cdist(X,kemans.cluster_centers_,'euclidean'),axis=1))/X.shape[0]
    meanDispersions.append(m_Disp)
 
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei'] #使折線圖顯示中文
 
plt.plot(K,meanDispersions,'bx-')
plt.xlabel('k')
plt.ylabel('平均離差')
plt.title('用肘部方法選擇K值')
plt.show()
           

三、執行個體分析(對某網站500家飯店價格及評論進行聚類)

import numpy as np
from sklearn.cluster import KMeans
from scipy.spatial.distance import cdist
import matplotlib.pyplot as plt
import pandas as pd
 
data=pd.read_excel('data.xlsx',header=0).iloc[:501,3:5]
per_25=data.describe().iloc[4,1]
per_75=data.describe().iloc[6,1]
data=data[(data.iloc[:,1]>=per_25)&(data.iloc[:,1]<=per_75)] #選擇位于四分位數之内的數
X=np.array(data)
 
 
K=range(1,10)
meanDispersions=[]
for k in K:
    kemans=KMeans(n_clusters=k)
    kemans.fit(X)
    meanDispersions.append(sum(np.min(cdist(X,kemans.cluster_centers_,'euclidean'),axis=1))/X.shape[0])
 
 
 
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.plot(K,meanDispersions,'bx-')
plt.xlabel('k')
plt.ylabel('平均離差')
plt.title('用肘部方法選擇K值')
plt.show()

具體聚類過程
 
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
 
kemans=KMeans(n_clusters=3)
result=kemans.fit_predict(X)
print(result)
x=[i[0] for i in X]
y=[i[1] for i in X]
plt.scatter(x,y,c=result,marker='o')
plt.xlabel('avgPrice')
plt.ylabel('llCommentNum')
plt.title('對500家飯店價格與評論數進行聚類')
           

聚類結果:

[2 0 0 0 0 1 0 0 2 0 0 2 1 2 0 1 2 0 2 2 2 0 0 0 0 1 2 0 1 0 0 2 2 2 2 2 2

2 2 0 1 0 0 0 1 0 2 2 0 2 2 0 0 2 2 2 1 0 1 1 1 0 0 0 0 1 2 1 2 0 2 1 0 0

2 1 1 0 0 1 2 2 0 2 2 1 0 2 1 0 2 0 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 2 1 2 1

1 0 0 1 0 1 2 1 0 1 1 0 1 1 0 1 0 2 1 1 0 1 0 2 0 2 1 2 1 1 0 0 1 0 1 0 1

0 2 0 1 1 0 1 0 0 1 1 1 1 0 0 0 0 1 0 0 0 2 0 1 1 0 1 0 1 0 0 0 0 1 1 0 1

2 0 1 1 2 0 1 0 0 1 1 1 1 1 0 0 0 1 1 1 2 0 1 1 1 2 2 0 0 2 1 1 2 1 1 1 0

1 1 0 1 2 2 0 2 2 2 0 1 0 1 1 2 1 1 1 0 1 1 1 1 0 0 0 0 1]

數學模組化——K-means聚類模型Python代碼