ファイナンス機械学習:特徴量の重要度 練習問題 特徴量とPCA変換特徴量を結合し、重要度を判定する。MDAでの負方向の大きな振れ

スニペットのtestFuncを変更して、人工のデータセットの特徴量と、これをPCA変換した特徴量を結合し、ランダムフォレストを使って、重要度を推定する。
 ランダムフォレストを使えるように、スニペット8.8を変更する。

def getFeatImportances(trnsX,cont,n_estimators=1000,cv=10,
                    max_samples=1.,numThreads=11,pctEmbargo=0,
                    scoring='accuracy',method='SFI',minWLeaf=0.,
                    RandomForest=False,**kargs):
    # feature importance from a random forest
    from sklearn.tree import DecisionTreeClassifier
    from sklearn.ensemble import RandomForestClassifier
    from sklearn.ensemble import BaggingClassifier
    import FinCV as fcv
    import Weights as wg
    #from mpEngine import mpPandasObj
    n_jobs=(-1 if numThreads>1 else 1) # run 1 thread w/ ht_helper in dirac1
    #1) prepare classifier,cv. max_features=1, to prevent masking
    if RandomForest is False:
        clf=DecisionTreeClassifier(criterion='entropy',max_features=1.,
                               class_weight='balanced',
                               min_weight_fraction_leaf=minWLeaf)
        clf=BaggingClassifier(estimator=clf,n_estimators=n_estimators,
                          max_features=1.,max_samples=max_samples,
                          oob_score=True,n_jobs=n_jobs)
        fit=clf.fit(X=trnsX,y=cont['bin'],sample_weight=cont['w'].values)
    else:
        CoEvents=wg.getNumCoEvents(trnsX.index, t1=cont['t1'], period=trnsX.index)
        avgUniq=wg.getSampleTW(t1=cont['t1'],numCoEvents=CoEvents,period=trnsX.index)
        avgU=avgUniq.mean()
        clf = RandomForestClassifier(n_estimators=n_estimators,
                                     criterion='entropy',
                                     max_features=1,
                                     class_weight="balanced_subsample",
                                     bootstrap=True,
                                     oob_score=True,
                                     n_jobs=-1,
                                     max_samples=None)
        fit=clf.fit(X=trnsX,y=cont['bin'],sample_weight=cont['w'].values)
    oob=fit.oob_score_
    y=cont['bin']
    if method=='MDI':
        imp=getFeatImpMDI(fit,featNames=trnsX.columns)
        oos=cvScore(clf,X=trnsX,y=y,cv=cv,sample_weight=cont['w'],
                    t1=cont['t1'],pctEmbargo=pctEmbargo,scoring=scoring).mean()
    elif method=='MDA':
        imp,oos=getFeatImpMDA(clf,X=trnsX,y=y,cv=cv,
                           sample_weight=cont['w'],t1=cont['t1'],
                           pctEmbargo=pctEmbargo,scoring=scoring)
    elif method=='SFI':
        cvGen=fcv.PurgedKFold(n_splits=cv,t1=cont['t1'],pctEmbargo=pctEmbargo)
        oos=cvScore(clf,X=trnsX,y=y,sample_weight=cont['w'],
                    scoring=scoring,cvGen=cvGen).mean()
        imp = getAuxFeatImpSFI(featNames=trnsX.columns, clf=clf, trnsX=trnsX, cont=cont,
                               scoring=scoring, cvGen=cvGen)
    return imp,oob,oos

テストデータを作成し、PCA変換したものと結合し、ランダムフォレストを使って、MDI ,MDA,SFIを適用する。

def EXER8_2(RandomForest=False,testlabel='XPCAX',n_estimators=1000,cv=10):
    from itertools import product
    import pathlib

    X,cont=getTestData()
    PCAX=getOrthoFeats(X)
    PCAX.index=X.index
    trnsX=pd.concat([X, PCAX], axis=1)

    testlabel='XPCAX'
    dict0={'minWLeaf':[0.],'scoring':['accuracy'],'method':['MDI','MDA','SFI'],
           'max_samples':[1.]}
    jobs,out=(dict(zip(dict0,i))for i in product(*dict0.values())),[]
    pdir=pathlib.Path()
    kargs={'pathOut':pathlib.PurePosixPath(pdir/testlabel),
           'n_estimators':n_estimators,'tag':testlabel,'cv':cv}

    for job in jobs:
        job['simNum']=job['method']+'_'+job['scoring']+'_'+'%.2f'%job['minWLeaf']+\
        '_'+str(job['max_samples'])
        kargs.update(job)
        imp,oob,oos=getFeatImportances(trnsX=trnsX,cont=cont,RandomForest=RandomForest,**kargs)
        plotFeatImportance(imp=imp,oob=oob,oos=oos,**kargs)
        df0=imp[['mean']]/imp['mean'].abs().sum()
        df0['type']=[i[0] for i in df0.index]
        df0=df0.groupby('type')['mean'].sum().to_dict()
        df0.update({'oob':oob,'oos':oos});df0.update(job)
        out.append(df0)
    out=(pd.DataFrame(out).sort_values(['method','scoring','minWLeaf','max_samples']))
    out=out[['method','scoring','minWLeaf','max_samples','I','R','N','O','oob','oos']]
    outfile=str(kargs['pathOut'])+'stats.csv'
    out.to_csv(outfile)
    return
MDI
MDA
SFI

MDAでは、実現可能な最大スコア(neg-log-lossならば0、正解率ならば1)と比較した特徴量の並べ替え後と前の改善度合いの関数として与えられている。よって、MDIとSFIとは違い、改善度がマイナスになる場合がある。
これが、MDAの結果でマイナスに大きく振れているORT0,R6,R3である。
この特徴量は実際には、アルゴリズムの予測力に悪影響をお及ぼしているとも言えることに注意すべきである。

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