階層クラスタリング

頭が整理できていないので、メモ

まとめること

キーワード

  • scipy.cluster.hierarchy
  • condensed distance matrix
  • redundant distance matrix
  • square-form distance matrix

やりたいこと

日株(TOPIX),米株(S&P500),日債,米債の4種資産を、相関関係をもとに階層クラスタリングで分類したい。

使用するライブラリ

  • scipy.cluster.hierarchy 公式ドキュメント

docs.scipy.org

引数に何を投入すればよい?

以下、公式ドキュメントより引用(linkageのところ)

Performs hierarchical/agglomerative clustering on the condensed distance matrix y.

距離行列を投入すればおっけーみたい。でも、condensed distance matrixとは?

距離行列関連

そもそも

今回の目的は相関関係をもとにクラスタ分けを行うことなので、相関係数行列をもとに4資産間の距離行列を算出することにしている。

具体的には、この論文で用いられている下の関数を使用。

    def correlDist(corr):
        # A distance matrix based on correlation, where 0<=d[i,j]<=1
        # This is a proper distance metric
        dist = ((1 - corr) / 2.) ** .5  # distance matrix
        return dist

例として、投入した相関係数行列と、出力された距離行列の組み合わせは以下。

相関係数行列 f:id:iiiiikamirin:20200723153409p:plain 距離行列 f:id:iiiiikamirin:20200723153737p:plain

距離行列の種類

公式ドキュメント内のcondensed distance matrixとは??というところから、距離行列の表記種類(距離の測定方法でなはくて)を自身の調べた限りでまとめてみる。

参考サイトは以下。

www.haya-programming.com

  • square-form distance matrix

おそらく最も馴染みのある形式。上の関数の出力distと同じ形式

  • condensed distance matrix

距離行列って「対象行列」かつ「対角成分は0」を満たすから、square-form distance matrixって無駄な情報多くない?っていう考え方から作成されたもの

square-form distance matrixをもとに、以下のコードで変換可能。

from scipy.spatial.distance import squareform
condensed_dist = squareform(dist) #  dist : squared_form

f:id:iiiiikamirin:20200723154854p:plain

  • redundant distance matrix

調べても出てこなかった、、

ただ、下のリンクではcondensedと対比して使われていることとredundantの「余分な」という意味と合わせて考えるとsquared_formと同じ意味ではないかと。 github.com

実装コード

引数もわかったことだし、コードを実装したのが以下。 ( (きってはってしたので、インテンドとかめちゃくちゃです、すみません。)

import scipy.cluster.hierarchy as sch
from scipy.cluster.hierarchy import dendrogram
from scipy.spatial.distance import squareform

    def correlDist(corr):
        # A distance matrix based on correlation, where 0<=d[i,j]<=1
        # This is a proper distance metric
        dist = ((1 - corr) / 2.) ** .5  # distance matrix
        return dist

corr = input_df.corr()
dist = self.correlDist(corr) #  dist行列を使用
condensed_dist = squareform(dist)
link = sch.linkage(condensed_dist, method='ward', metric='euclidean')
        
#          樹形図保存
fig = dendrogram(link, labels=self.corr.index.values)
plt.xticks(rotation=315, ha='left')
plt.savefig("output/dendrogram.png", bbox_inches='tight', pad_inches=0)
plt.figure()

f:id:iiiiikamirin:20200723161647p:plain

樹形図見た感じよさそう。一応linkageを確認。linkage各要素については、以下リンクを参考。

qiita.com

linkageの出力結果は以下。

[[0.         1.         0.65309278 2.        ]
 [2.         3.         0.66734477 2.        ]
 [4.         5.         0.89813174 4.        ]]

4資産間の距離は以下の通り。(見やすいのでsquared_formf:id:iiiiikamirin:20200723153737p:plain

index0:日株とindex1:米株の距離、およびindex2:日債とindex3:米債の距離が投入したものと同じであることが確認できた。

ところで

github.com

上のこのリンク内で、

scipy.cluster.hierarchyってredundant distance matrixいれても大丈夫、とかいってるけど、実際にいれてみたらdistance matrixのことをobserved matrixと勘違いしてません??」

みたいなこと言われていたのが気になる。。(この論文中ではsquared_formの距離行列をそのままscipyにつっこんでるし)

確認してみた。

import scipy.cluster.hierarchy as sch
from scipy.cluster.hierarchy import dendrogram
from scipy.spatial.distance import squareform

    def correlDist(corr):
        # A distance matrix based on correlation, where 0<=d[i,j]<=1
        # This is a proper distance metric
        dist = ((1 - corr) / 2.) ** .5  # distance matrix
        return dist

corr = input_df.corr()
dist = self.correlDist(corr) #  dist行列を使用
#condensed_dist = squareform(dist)
#link = sch.linkage(condensed_dist, method='ward', metric='euclidean')
link = sch.linkage(dist, method='ward', metric='euclidean')
        
#          樹形図保存
fig = dendrogram(link, labels=self.corr.index.values)
plt.xticks(rotation=315, ha='left')
plt.savefig("output/dendrogram.png", bbox_inches='tight', pad_inches=0)
plt.figure()

f:id:iiiiikamirin:20200723163519p:plain

linkageはこちら

[[0.         1.         0.93768267 2.        ]
 [2.         3.         0.95778144 2.        ]
 [4.         5.         1.2899719  4.        ]]

データ間の距離は確かに変わっちゃってる。そして、distを観測行列として求めたデータ間のユークリッド距離と一致していた。

うーーん、まあこれでもデータ間のユークリッド距離の大小関係は崩れないとおもうんだけど、なんか気持ち悪さは残る、、(でも前会社で「別にこれでも(多分)大小関係崩れないからよくないですか??」とか適当に言ったことはある)

まあcondensed distance matrixを投入すればいいだけの話かなあ。