ファイナンス機械学習:特徴量の重要度 練習問題 特徴量と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
MDAでは、実現可能な最大スコア(neg-log-lossならば0、正解率ならば1)と比較した特徴量の並べ替え後と前の改善度合いの関数として与えられている。よって、MDIとSFIとは違い、改善度がマイナスになる場合がある。
これが、MDAの結果でマイナスに大きく振れているORT0,R6,R3である。
この特徴量は実際には、アルゴリズムの予測力に悪影響をお及ぼしているとも言えることに注意すべきである。
この記事が気に入ったらサポートをしてみませんか?