アセットマネージャーのためのファイナンス機械学習:クラスター数 ONCアルゴリズム モンテカルロ

 ブロックの数と構成を再現するONCアルゴリズムを使い、行と列をシャッフルされた$${M \ge 2}$$のサイズのブロックK個からなる$${N\times N}$$のランダムな相関行列を復元する。
$${N=16,32,64}$$、$${K=3,6,\dots N/2}$$、試行回数を100、ONCアルゴリズムによって決定されたクラスター数の$${E[K]}$$の$${K}$$からの乖離$${E[K]/K}$$として表し、$${K/N}$$毎に示す。

 モンテカルロシミュレーションのコードは以下の通りである。
 

import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_samples
from scipy.linalg import block_diag
from sklearn.utils import check_random_state
import MarPat as MP
import ONC
import pickle

def ShuffleMatrix(bCorr,random_state=None):
    rng=check_random_state(random_state)
    corr0=pd.DataFrame(bCorr)
    cols=corr0.columns.tolist()
    rng.shuffle(cols)
    corr0=corr0[cols].loc[cols].copy(deep=True)
    return corr0

N=[16,32,64]

M=2
num=100

print('start')
for n in N:
    print(n)
    results={}
    file_name=f'results_{n}'
    for k in range(3,int(n/2)+1,3):
        key=k/n
        E=0
        for i in range(1,num):
            corr0 = ONC.randomBlockCorr(n, k, minBlockSize=M)
            corr1 = ShuffleMatrix(corr0)
            corr1New, clstrs1New, silh1New = ONC.clusterKMeansTop(corr1)
            E=len(clstrs1New)/k
            results.setdefault(key,[]).append(E)
        with open(file_name, 'wb') as fp:
        pickle.dump(results, fp)
        print('dictionary saved successfully to file')


print('sim end')

 ONCは決して効率の良いコードではなく、Nが大きくなればなるほど時間がかかるので、計算時間の関係から結果をファイルに書き出している。
 シミュレーション結果の計算処理は重くはないので、ファイルを読み込んで行う。

import pickle
from collections import defaultdict
import pandas as pd

results = defaultdict(list)

N=[16,32,64]

for n in N:
    file_name='results_'+str(n)
    with open(file_name,'rb') as fp:
        result = pickle.load(fp)
        for key,val in result.items():
            results[key]+=val


df=pd.DataFrame()
for mky,mv in results.items():
    n_mv=len(mv)
    avg=sum(mv)/n_mv
    err=0.0
    for i in range(n_mv):
        err+=(mv[i]-avg)*(mv[i]-avg)
    err/=n_mv
    list_=[[mky,round(avg,3),round(err,8)]]
    df_new=pd.DataFrame(list_,columns=['K/N','E[K]/K','ERR'])
    df=pd.concat([df,df_new])

 シミュレーション結果は辞書形式で、keyを$${K/N}$$、値をリスト形式にして平均値と平均二乗誤差を計算し、データフレームで出力した。

ONC

$${K/N}$$が小さい値ではエラーが見られるが、$${K/N \ge 0.3}$$では良い結果を出していると言える。

この記事が気に入ったらサポートをしてみませんか?