使用k-means及k-prototype對混合型數據集進行聚類分析

1. 分析目標

本項目旨在使用聚類算法對110個城市進行分類與排序,以尋找客觀真實的城市分層方法、支持業務運營與決策。node

2. 數據集

數據集來源於某互聯網公司,特徵值標籤已作脫敏處理。數據集尺寸爲111行×5列,第一行爲標題行,其他110行爲實例。python

  • 第一列:城市名,將做爲index不參與模型計算;
  • 第二列:特徵值a,以數值表現的分類變量,1表明評價最好、4表明最差;
  • 第三列:特徵值b,數值型變量,數值越高對業務積極影響越大;
  • 第四列:特徵值c,數值型變量,數值越高對業務消極影響越大;
  • 第五列:特徵值d,數值型變量,數值越高對業務積極影響越大。

3. 方法論

首先,因爲數據集呈現分類變量與數值變量混合的特色,本次數據分析將採用如下兩種算法並在分析結束後進行對比擇優:算法

  • K-means算法:須要將分類變量a轉換爲啞變量,使其成爲數值型變量,而後經過計算歐幾里得距離得出聚類結果。算法運行結束後將使用輪廓係數評價聚類效果。
  • K-prototype算法:無需建立啞變量,將分別爲分類變量計算漢明距離、爲數值型變量計算歐幾里得距離而後得出聚類結果。算法運行結束後將使用成本函數評價聚類效果。

其次,數值型變量b、c、d的量綱明顯不等,爲避免量綱影響距離計算中不一樣變量的權重,須要對變量b、c、d進行處理。因爲不知道是否符合正態分佈,在這裏使用歸一化而非標準化。shell

最後,因爲機器沒法理解業務場景,算法自己沒法對不一樣聚類進行排序。在找到合理聚類方法後須要人工構建一個聚類評價指標以實現排序。app

本項目基於python 3.7.3,使用的庫包括pandas、numpy、sklearn、matplotlib、seaborn、kmodes,具體代碼詳見附錄。函數

4. 預處理

預處理步驟包括:spa

  • 使用MinMaxScaler對變量b,c,d進行歸一化
  • 使用get_dummies爲變量a建立啞變量

處理結束後的數據集以下所示(僅展現前五行爲例):prototype

城市3d

a_1code

a_2

a_3

a_4

a

b

c

d

三亞

0

0

1

0

3

0.016206

0.009198

0.00757

上海

1

0

0

0

1

1

1

1

東莞

0

0

1

0

3

0.314485

0.187345

0.299205

中山

0

0

0

1

4

0.109215

0.060833

0.057343

臨沂

0

0

0

1

4

0.106044

0.035673

0.018547

5. 分析過程

5.1 K-means

 

  • 參與運算的列:a_1,a_2,a_3,a_4,b,c,d
  • 手肘法求解最優k值(聚類數量):k=3
  • k=3時的輪廓係數評價:

  • 聚類間距:

  • 解讀:雖然聚類間距良好,可是聚類2的輪廓係數太低,說明聚類2的聚合效果很差。在檢視聚類2時發現其包含北京、上海、牡丹江、大慶等城市,有悖常規認知,說明該聚類不合理。
  • 結論:k-means聚類結果不可用。

5.2 K-prototype

  • 參與運算的列:a,b,c,d
  • 手肘法求解最優k(使用成本函數製圖):k=4

注1:python中計數從0開始計,因此橫軸數值爲聚類數量-1

注2:此方法結果具備隨機性,有時會產生不止一個肘點,存在最優解和次優解。爲確保k=3爲最優解,此過程被運行了十次,最後驗證最優解衆數爲3。

  • 解讀:分爲四個聚類時,四個聚類所包含的城市符合1、2、3、四線城市的常規認知,說明聚類接近真實狀況。
  • 結論:K-prototype的聚類結果較爲真實客觀,能夠採用。

6. 聚類排序

爲實現聚類排序,首先調取了每一個聚類的質點:

 

CentroidsMin-max Scaled

Centroids(原數據)

 

Cluster

a

b

c

d

a

b

c

d

Count

0

4

0.05

0.02

0.01

4

3853.19

6638.98

56.46

48

1

2

0.66

0.52

0.59

2

38517.47

178333.07

3119.33

6

2

2

0.31

0.17

0.15

2

18678.75

60002.46

785.96

24

3

3

0.10

0.04

0.03

3

7053.54

16004.42

148.87

32

此處須要基於業務理解構建一個做爲聚類評價指標。四個特徵值的業務重要程度一致,所以須要採用等權重計算每一個特徵值的,可是變量c對總的貢獻爲負。可是,考慮到量綱的影響,仍需使用歸一化的b、c、d做爲其。若是將a做爲數值型變量進行考量,也應當進行歸一化處理,而且應注意數值越大實際上對的貢獻越低。綜上所述,的構建方法以下:

其中,

經計算,每一個聚類的及排名以下:

Cluster

Score

Ranking

0

0.04

4

1

1.40

1

2

0.95

2

3

0.42

3

經檢視,聚類一、二、三、0很是接近常規認知中的1、2、3、四線城市,證實排序合理。

 

7. 結論

通過使用k-prototype算法和構建聚類評價指標,成功將110個城市分爲四個聚類及聚類排序。同時運用評價指標,結合歸一化數據可對個體城市實現細粒度上的評價,從而獲得每一個聚類內部的城市排名狀況或跨四個聚類的整體城市排名:

城市

a

 b

c

 d

cluster

cluster_tag

in-cluster_score

in-cluster_ranking

上海

1

57874

342463

5286

1

tier1

1.510

1

北京

2

40210

182647

3457

1

tier1

1.162

2

深圳

3

37620

160159

3228

1

tier1

1.116

3

蘇州

2

34424

117925

1871

1

tier1

0.897

4

廣州

3

29242

105356

2288

1

tier1

0.875

5

杭州

2

31735

161448

2586

1

tier1

0.834

6

 

城市

a

 b

c

 d

cluster

cluster_tag

in-cluster_score

in-cluster_ranking

東莞

3

18958

64856

1583

2

tier2

0.587

1

南京

2

23572

84459

1266

2

tier2

0.592

2

南昌

2

10282

36616

639

2

tier2

0.260

3

廈門

1

15059

70708

1073

2

tier2

0.369

4

合肥

2

18372

75802

724

2

tier2

0.377

5

哈爾濱

2

16126

29936

332

2

tier2

0.377

6

嘉興

2

10918

35879

370

2

tier2

0.228

7

大連

2

13676

31977

358

2

tier2

0.311

8

天津

2

25428

65309

1010

2

tier2

0.649

9

寧波

2

21712

64354

928

2

tier2

0.538

10

常州

2

12683

29769

355

2

tier2

0.290

11

成都

3

30619

95611

918

2

tier2

0.681

12

無錫

2

18622

42607

632

2

tier2

0.463

13

武漢

2

21566

92360

1399

2

tier2

0.541

14

瀋陽

2

23688

67889

735

2

tier2

0.543

15

泉州

2

15615

63454

761

2

tier2

0.346

16

溫州

1

22346

72011

903

2

tier2

0.527

17

湖州

2

6299

17706

156

2

tier2

0.118

18

福州

1

15067

82398

1031

2

tier2

0.327

19

西安

3

23634

57532

1118

2

tier2

0.645

20

重慶

3

31119

76562

656

2

tier2

0.701

21

金華

2

15317

48394

568

2

tier2

0.346

22

長沙

2

19307

77104

822

2

tier2

0.416

23

青島

2

18305

56769

526

2

tier2

0.393

24

 

城市

a

 b

c

 d

cluster

cluster_tag

in-cluster_score

in-cluster_ranking

三亞

3

2025

4000

42

3

tier3

0.023

1

九江

3

4582

8585

56

3

tier3

0.080

2

南寧

3

9909

23157

361

3

tier3

0.237

3

南通

3

10861

29783

219

3

tier3

0.216

4

台州

3

11892

27683

221

3

tier3

0.250

5

吉林

3

4658

6652

31

3

tier3

0.083

6

咸陽

3

3754

5903

49

3

tier3

0.065

7

太原

3

7675

16814

248

3

tier3

0.175

8

惠州

3

9378

29550

448

3

tier3

0.220

9

揚州

3

6396

16309

141

3

tier3

0.122

10

新鄉

3

4417

6036

58

3

tier3

0.084

11

泰州

3

5609

15036

57

3

tier3

0.089

12

濟南

3

13485

32222

297

3

tier3

0.293

13

淄博

3

4308

9902

68

3

tier3

0.071

14

湛江

3

3243

6016

36

3

tier3

0.048

15

濰坊

3

8754

20406

201

3

tier3

0.184

16

煙臺

3

7611

15206

110

3

tier3

0.152

17

珠海

3

4775

12372

116

3

tier3

0.085

18

鹽城

3

7908

21129

113

3

tier3

0.143

19

石家莊

3

13750

29776

462

3

tier3

0.339

20

紹興

3

7073

22799

188

3

tier3

0.130

21

蕪湖

3

4555

11467

63

3

tier3

0.072

22

荊州

3

3325

4988

20

3

tier3

0.050

23

營口

3

3574

5605

19

3

tier3

0.055

24

蚌埠

3

2961

6873

38

3

tier3

0.039

25

贛州

3

7994

16110

172

3

tier3

0.171

26

鄭州

3

18906

42977

432

3

tier3

0.432

27

銀川

3

6829

10248

149

3

tier3

0.153

28

鎮江

3

6047

20610

101

3

tier3

0.092

29

長春

3

12492

22492

208

3

tier3

0.279

30

黃石

3

2118

4601

22

3

tier3

0.020

31

齊齊哈爾

3

4850

6836

18

3

tier3

0.085

32

 

城市

a

 b

c

 d

cluster

cluster_tag

in-cluster_score

in-cluster_ranking

中山

4

7305

21639

305

0

tier4

0.161

1

臨沂

4

7125

13044

100

0

tier4

0.143

2

烏魯木齊

4

1825

858

5

0

tier4

0.020

3

佛山

4

11138

33369

560

0

tier4

0.277

4

佳木斯

1

3781

6769

20

0

tier4

0.057

5

蘭州

4

5566

10263

128

0

tier4

0.115

6

包頭

4

2032

1750

27

0

tier4

0.027

7

呼倫貝爾

4

2499

2107

5

0

tier4

0.034

8

呼和浩特

4

3444

3478

63

0

tier4

0.066

9

唐山

4

4240

5776

25

0

tier4

0.073

10

商丘

4

4619

5356

17

0

tier4

0.083

11

大同

4

2213

2399

8

0

tier4

0.026

12

大慶

2

4379

4913

12

0

tier4

0.077

13

威海

2

5125

10654

83

0

tier4

0.094

14

安陽

4

2582

2371

21

0

tier4

0.038

15

宜昌

4

3298

3941

15

0

tier4

0.052

16

寶雞

4

2565

1789

12

0

tier4

0.038

17

宿遷

4

3054

5249

19

0

tier4

0.042

18

岳陽

4

2784

3660

13

0

tier4

0.039

19

延邊

4

3315

4166

6

0

tier4

0.050

20

開封

4

3523

2555

8

0

tier4

0.060

21

徐州

4

8302

16204

87

0

tier4

0.163

22

揭陽

2

4710

11208

90

0

tier4

0.082

23

日照

4

1190

2352

4

0

tier4

-0.002

24

昆明

4

8389

18251

177

0

tier4

0.176

25

景德鎮

1

2304

5690

63

0

tier4

0.029

26

柳州

4

2279

4194

4

0

tier4

0.022

27

桂林

4

3379

4137

23

0

tier4

0.055

28

江門

4

2978

5948

27

0

tier4

0.040

29

瀘州

4

2023

2084

5

0

tier4

0.021

30

洛陽

4

4999

4765

38

0

tier4

0.099

31

濟寧

4

6007

11411

93

0

tier4

0.117

32

海口

4

4678

17398

148

0

tier4

0.074

33

淮北

4

1105

1636

8

0

tier4

-0.001

34

淮安

4

4921

8405

34

0

tier4

0.085

35

牡丹江

1

4140

5646

20

0

tier4

0.070

36

秦皇島

4

2449

2005

18

0

tier4

0.035

37

綿陽

4

2895

4501

28

0

tier4

0.042

38

肇慶

4

2932

5465

47

0

tier4

0.044

39

舟山

1

2430

6081

40

0

tier4

0.027

40

西寧

4

1710

1616

19

0

tier4

0.017

41

貴陽

4

4506

7772

181

0

tier4

0.104

42

赤峯

4

3819

3971

19

0

tier4

0.066

43

運城

4

2850

1866

3

0

tier4

0.044

44

連雲港

4

3454

6768

40

0

tier4

0.052

45

通遼

4

1702

1491

2

0

tier4

0.014

46

遵義

4

4835

5303

28

0

tier4

0.091

47

鞍山

4

3555

6398

12

0

tier4

0.051

48

 

 

 

 

附錄:代碼

K-means

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
%matplotlib inline
import pandas as pd
import numpy as np
from sklearn import preprocessing
from sklearn.cluster import KMeans
from sklearn.cluster import MiniBatchKMeans
from yellowbrick.cluster import KElbowVisualizer
from yellowbrick.cluster import SilhouetteVisualizer
from yellowbrick.cluster import InterclusterDistance
from yellowbrick.model_selection import LearningCurve
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("whitegrid")
sns.set_context("notebook")

df = pd.read_csv('practice_2_clustering_with_cat.csv')
df.head()
df['a'] = df['a'].astype(object)
dummies = pd.get_dummies(df['a'], prefix='a')
bcd = df.iloc[:, 2:5]

min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(bcd)
X_scaled = pd.DataFrame(x_scaled,columns=bcd.columns)
X_scaled = pd.concat([X_scaled,dummies], axis=1,)

# Elbow method 手肘法
plt.figure(figsize=(12,9))

model = KMeans()

visualizer = KElbowVisualizer(model, k=(1,8))
visualizer.fit(X_scaled)       
visualizer.show()

model=MiniBatchKMeans(n_clusters=3)
model.fit(X_scaled)
print("Predicted labels ----")
model.predict(X_scaled)
df['cluster'] = model.predict(X_scaled)

plt.figure(figsize=(12,9))

model=MiniBatchKMeans(n_clusters=3).fit(X_scaled)

visualizer = SilhouetteVisualizer(model, colors='yellowbrick')
visualizer.fit(X_scaled)      
visualizer.show()

plt.figure(figsize=(12,9))

visualizer = InterclusterDistance(model, min_size=10000)
visualizer.fit(X_scaled)
visualizer.show()

df = pd.concat([df,X_scaled], axis=1)
df

K-prototype

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
%matplotlib inline
import pandas as pd
import numpy as np
from sklearn import preprocessing
from sklearn.cluster import KMeans
from sklearn.cluster import MiniBatchKMeans
from yellowbrick.cluster import KElbowVisualizer
from yellowbrick.cluster import SilhouetteVisualizer
from yellowbrick.cluster import InterclusterDistance
from yellowbrick.model_selection import LearningCurve
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("whitegrid")
sns.set_context("notebook")
import numpy as np
import pandas as pd
from kmodes.kprototypes import KPrototypes
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.read_csv('practice_2_clustering_with_cat.csv')
df.head()
df['a'] = df['a'].astype(object)

X = df.iloc[:, 1:5]
X.columns = ['a','b','c','d']
X.head()

min_max_scaler = preprocessing.MinMaxScaler() 
bcd = X.iloc[:,1:4]
x_scaled = min_max_scaler.fit_transform(bcd)
X_scaled = pd.DataFrame(x_scaled,columns=bcd.columns)
X = pd.concat([df['a'],X_scaled], axis=1)

X_matrix = X.values
cost = []
for num_clusters in list(range(1,9)):
    kproto = KPrototypes(n_clusters=num_clusters, init='Cao')
    kproto.fit_predict(X_matrix, categorical=[0])
    cost.append(kproto.cost_)
    
plt.plot(cost)
pd.DataFrame(cost)

kproto = KPrototypes(n_clusters=6, init='Cao')
clusters = kproto.fit_predict(X_matrix, categorical=[0])
print('====== Centriods ======')
kproto.cluster_centroids_
print()
print('====== Cost ======')
kproto.cost_

centroids = pd.concat([pd.DataFrame(kproto.cluster_centroids_[1]),pd.DataFrame(kproto.cluster_centroids_[0])], axis=1)
centroids
df['cluster'] = clusters
df.head()
相關文章
相關標籤/搜索