階層的クラスタリング

やること

階層的クラスタリングについて、手を動かしてみる

参考サイト

qiita.com

今回も参考サイトを写した

やったこと

都道府県別アルコール消費量のデータをもとに、47都道府県をクラスタリング

とりあえず、参考サイトの言われるままに、データをダウンロードしてデータフレーム作成

%matplotlib inline
import urllib.request
import pandas as pd
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import linkage, dendrogram

url = 'https://raw.githubusercontent.com/maskot1977/ipython_notebook/master/toydata/sake_dataJ.txt'

urllib.request.urlretrieve(url,'sake_dataJ.txt')
df = pd.read_csv('sake_dataJ.txt', sep = '\t', index_col = 0)
print (df.head(7))

結果

               Sake    Shochu       Bear      Wine   Whisky
Pref                                                       
Hokkaido   46476000  50642000  315300000  10488000  9749000
Aomori     17273000  11503000   83164000   1774000  3122000
Iwate      17120000  10220000   67803000   1458000  1870000
Miyagi     27859000  11768000  109850000   2824000  5049000
Akita      24153000   6240000   67894000   1242000  2099000
Yamagata   20570000   6067000   61130000   1706000  2466000
Fukushima  31016000  11166000  100122000   1885000  3807000

特徴量行列を変えてみる

参考記事で書かれている通り、特徴量行列を色々変えてみる

正しいやつ

都道府県別アルコール消費量のデータフレームを、行ごとに正規化

正規化した特徴量行列を用いて、クラスタリング

dfs = df.apply(lambda x: (x - x.mean()) / x.std(), axis = 1).fillna(0)
print (dfs.head(7))
result1 = linkage(dfs.iloc[:, :], 
                  metric = 'correlation', 
                  method = 'average')
plt.figure(figsize=(8, 8))
dendrogram(result1, orientation='right', labels=list(df.index), color_threshold=0.01)
plt.title("Dedrogram")
plt.xlabel("Threshold")
plt.show()

結果

               Sake    Shochu      Bear      Wine    Whisky
Pref                                                       
Hokkaido  -0.309710 -0.277498  1.768869 -0.587973 -0.593687
Aomori    -0.179131 -0.348733  1.757648 -0.634704 -0.595081
Iwate     -0.093054 -0.342479  1.739063 -0.659212 -0.644319
Miyagi    -0.080427 -0.438818  1.745738 -0.638025 -0.588468
Akita      0.135911 -0.500179  1.689151 -0.677657 -0.647225
Yamagata   0.087023 -0.491336  1.704499 -0.665247 -0.634939
Fukushima  0.034493 -0.448771  1.716934 -0.674724 -0.627932

f:id:iiiiikamirin:20200409230224p:plain

列ごとに正規化しちゃったパターン

# dfs = df.apply(lambda x: (x - x.mean()) / x.std(), axis = 1).fillna(0)
dfs1 = df.apply(lambda x: (x - x.mean()) / x.std(), axis = 0).fillna(0)
print (dfs1.head(7))
result1 = linkage(dfs1.iloc[:, :], 
                  metric = 'correlation', 
                  method = 'average')
plt.figure(figsize=(8, 8))
dendrogram(result1, orientation='right', labels=list(df.index), color_threshold=0.01)
plt.title("Dedrogram")
plt.xlabel("Threshold")
plt.show()

結果

               Sake    Shochu      Bear      Wine    Whisky
Pref                                                       
Hokkaido   0.811237  2.147580  1.057634  1.029017  1.207049
Aomori    -0.437580 -0.210625 -0.389028 -0.298893 -0.126779
Iwate     -0.444123 -0.287929 -0.484757 -0.347047 -0.378772
Miyagi     0.015112 -0.194659 -0.222722 -0.138885  0.261072
Akita     -0.143369 -0.527732 -0.484190 -0.379963 -0.332681
Yamagata  -0.296590 -0.538156 -0.526343 -0.309255 -0.258814
Fukushima  0.150116 -0.230930 -0.283346 -0.281978  0.011092

f:id:iiiiikamirin:20200409230527p:plain

全然違う結果になった

正規化しなかったパターン

print (df.head(7))
result1 = linkage(df.iloc[:, :], 
                  metric = 'correlation', 
                  method = 'average')
plt.figure(figsize=(8, 8))
dendrogram(result1, orientation='right', labels=list(df.index), color_threshold=0.01)
plt.title("Dedrogram")
plt.xlabel("Threshold")
plt.show()

結果

               Sake    Shochu       Bear      Wine   Whisky
Pref                                                       
Hokkaido   46476000  50642000  315300000  10488000  9749000
Aomori     17273000  11503000   83164000   1774000  3122000
Iwate      17120000  10220000   67803000   1458000  1870000
Miyagi     27859000  11768000  109850000   2824000  5049000
Akita      24153000   6240000   67894000   1242000  2099000
Yamagata   20570000   6067000   61130000   1706000  2466000
Fukushima  31016000  11166000  100122000   1885000  3807000

f:id:iiiiikamirin:20200409230843p:plain

変えた結果について

そもそも行ごとに正規化する目的は、都道府県ごとの消費量の大小の影響を無くすこと(アルコール類の中で、どの種類の割合が多いかのみに着目して、クラスタリングするため)

だから、列ごとに正規化すると全然違う結果になる

一方、正規化しなかった場合と正規化した場合の結果は、違いがないように見られた

これはなぜ??