ファイナンス機械学習:特徴量の重要度 並列計算法

20の特徴量のうち、5は有益で、5は冗長であるサンプリング数1000,00個のデータセットを作り、10に分割する。
 分割されたデータセット$${\{(X_i, y_i)\}i=1,\dots,10}$$のそれぞれについて特徴量の重要度推定を行う。これは特徴量重要度の並列計算法の、10個の証券を持つ投資ユニバースの各証券$${i}$$についての特徴量$${j,j=1,\dots,20}$$の重要度だと見なすことができる。

import FeatImp as fti


if __name__ == '__main__':
    from itertools import product
    import pathlib
    n_features=20
    n_informative=5
    n_redundant=5
    n_estimators=1000
    n_samples=1e5
    cv=10
    testlabel='NonParallel'
    Split=1


    X, cont = fti.getTestData(n_features=n_features,
                              n_informative=n_informative,
                              n_redundant=n_redundant,
                              n_samples=int(n_samples))
    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)

        importances = pd.DataFrame(dtype=object)
        gobs = []
        goos = []
        for i in range(Split):
            testlabelNum=testlabel+str(i)
            kargs['pathOut']=pathlib.PurePosixPath(pdir/testlabelNum)
            imp,oob,oos=fti.getFeatImportances(
                    trnsX=X[i*int(n_samples/Split):(i+1)*int(n_samples/Split)],
                    cont=cont[i*int(n_samples/Split):(i+1)*int(n_samples/Split)],
                    **kargs)
            fti.plotFeatImportance(imp=imp,oob=oob,oos=oos,**kargs)
            imp.columns = ['mean_' + str(i), 'std_' + str(i)]
            importances=pd.concat([importances,imp],axis=1)
            gobs.append(oob)
            goos.append(oos)
        kargs['pathOut']=pathlib.PurePosixPath(pdir/testlabel)
        outfile=str(kargs['pathOut'])+job['method']+'Imp.csv'
        importances.to_csv(outfile)

コードでは、100,000のサンプルサイズをいっぺんに作ったが、10,000のデータセットを10回にわけて作っても良い。
 ただし、のちに一個のデータセットに結合するので、計算機負荷が高くなるのは変わらない。
 並列計算法をこのデータ数で実行するには、計算量が少ないMDIでも、大型クラスターでの並列化が必須である。この練習問題を試行するには、使用できるリソースを考えて行うことをお勧めする。

def plotFeatPara(df,title='MDI'):
    for j in range(len(df.index)):
        value=[]
        std_v=[]
        for i in range(0,10):
            split='mean_'+str(i)
            value.append(df.iloc[j][split])
            split='std_'+str(i)
            std_v.append(df.iloc[j][split])
        name=PARAMDI.iloc[j,0]
        plt.errorbar(range(0,10),value,yerr=std_v,label=name,marker='o',linestyle='None')
        plt.legend(bbox_to_anchor=(1.0, 1.0))
        plt.xlabel('Security i')
        plt.ylabel(title)

MDI

MDI

MDA

MDA

SFI

SFI

次の記事で、10のデータセットを結合し、一つの大規模データセットとするStucking法との違いを扱う。

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