ファイナンス機械学習:特徴量の重要度 特徴量の直交化

 特徴量同士に相関関係があると、代替効果によって、MDIやMDA推定で重要度が下げられる傾向がある。
 特徴量の次元削減で用いたPCAを用い、特徴量の直交化により、特徴量の線形関係が消滅すれば、代替効果のない特徴量の重要度解析が可能になる
 定常な特徴量行列を$${X_{t,n}}$$を考える、ここで、時間のバーと特徴量数について$${t=1,\dots,T, n=1,\dots.N}$$とする。
 直交化の前に、この行列を、各特徴量の時間(T)平均値$${\mu_n}$$と分散$${\sigma_n}$$を使い標準化する。
 $${Z_{t,n}=\displaystyle{\frac{X_{t,n}-\mu_nu}{\sigma_n}}}$$
この作業によって、特徴量の分散に左右されず、また平均値で中心化することにより特徴量の主方向が明確になる。
 固有値分解により、$${{\bf Z}}$$の対角化は
$${{\bf Z}^{T}\{bf ZW}=W\varLambda}$$
なる、固有ベクトル行列$${{\bf W}}$$と固有値を対角に並べた$${{\bf \varLambda}}$$で、$${{\bf P}={\bf ZW}}$$で与えられる。
 この対角化の実装はスニペット8.5で与えられている。
 ここで、分散閾値を95%と与え、これで与えられる直交特徴量に制限している。

def get_eVec(dot,varThres):
    # compute eVec from dot proc matrix, reduce dimension
    eVal,eVec=np.linalg.eigh(dot)
    idx=eVal.argsort()[::-1] # arugments for sorting eVal desc.
    eVal,eVec=eVal[idx],eVec[:,idx]
    #2) only positive eVals
    eVal=(pd.Series(eVal,index=['PC_'+str(i+1)
                                for i in range(eVal.shape[0])]))
    eVec=(pd.DataFrame(eVec,index=dot.index,columns=eVal.index))
    eVec=eVec.loc[:,eVal.index]
    #3) reduce dimension, form PCs
    cumVar=eVal.cumsum()/eVal.sum()
    dim=cumVar.values.searchsorted(varThres)
    eVal,eVec=eVal.iloc[:dim+1],eVec.iloc[:,:dim+1]
    return eVal,eVec

def getOrthoFeats(dfx,varThres=0.95):
    # given a DataFrame, dfx, of features, compute orthofeatures dfP
    dfZ=dfx.sub(dfx.mean(),axis=1).div(dfx.std(),axis=1) # standardize
    dot=(pd.DataFrame(np.dot(dfZ.T,dfZ),
                      index=dfx.columns,
                      columns=dfx.columns))
    eVal,eVec=get_eVec(dot,varThres)
    dfP=np.dot(dfZ,eVec)
    return pd.DataFrame(dfP).add_prefix("ORT_")

 この作業により、小さい固有値を持つ特徴量は省略され、特徴量次元は削減される。新しい特徴量次元は、元々に与えられている特徴量とは異なり、PCA重要度解析によるランク付は固有値の値によるランク付けで、教師有り学習のMDI、MDA,SFIとは違い、教師無し学習による結果である。
 この直交した特徴量に適用したMDI,MDA,SFI解析によって得られた重要度の順位付けと、PCA順位付けのケンドールの荷重$${\tau}$$を計算することで、この二つの順位付けの一貫性を判定することができる。
 ここで、荷重$${\tau}$$とするのは、最も重要な特徴量を重要視しているからである。
 ケンドールの荷重$${\tau}$$の計算は、scikit-learnのコードを使う(スニペット8.6)

from scipy.stats import weightedtau
featImp=np.array([0.55,0.33,0.07,0.05]) # feature importance
pcRank=np.array([1,2,3,4],dtype=np.float64) # PCA rank
weightedtau(featImp,pcRank**-1)[0]

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