ファイナンス機械学習:特徴量の重要度 並列計算法
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
MDA
SFI
次の記事で、10のデータセットを結合し、一つの大規模データセットとするStucking法との違いを扱う。
この記事が気に入ったらサポートをしてみませんか?