はじめに
背景
gcForest(multi-Grained Cascade Forest)の精度は画像認識や、感情分析、音楽分類、手の動きの分類などにおいて、一部の深層学習モデルとRandom Forestsの精度よりも高いことが知られている。
内容
本ページでは次のような決定木ベースの機械学習モデルを構築する。
- Random Forests
- gcForest
大規模なアンケートデータを想定し、Random Forestsの精度がgcForestの精度よりも高いことを示す。つまり、gcForestの苦手な部分を検証してみる。
学銃的な背景とインストール方法
前回の深い森(multi-Grained Cascade Forest)と浅い森(Random Forests)を動かして比較してみたを参照してください。
import numpy as np
import pandas as pd
import random
import uuid
from sklearn.datasets import make_classification
from sklearn.model_selection import StratifiedKFold, cross_validate
from sklearn.metrics import accuracy_score, cohen_kappa_score, balanced_accuracy_score, make_scorer, f1_score, recall_score
from sklearn.datasets import fetch_mldata
from sklearn.ensemble import ExtraTreesClassifier, RandomForestClassifier
from sklearn.metrics import accuracy_score, f1_score
from sklearn.model_selection import train_test_split
from deep_forest import MGCForest
実験
テスト用のデータ作成
パラメータの値
- n_samples: サンプルの数
- アンケート調査であれば回答者数に該当
- n_features: 特徴量の数
- 分類対象(クラス)を識別するために利用する特徴量の数
- 例えば、アンケート調査であれば質問と回答のペア
- n_informative:分類対象と関係のある特徴量の数
- この数が多ければ多いほど予測が簡単になる
- n_classes: 分類対象が何種類あるか
- 2値分類問題にするならば 2 をセット
- random_state: ランダムシードの設定
data = make_classification(n_samples=1000, #生成するサンプル数
n_features=110,
n_informative=100,
weights=[0.5,0.5],
n_classes=2,
random_state=43)
data_set = data[0] # 特徴量
target_set = data[1] # クラスラベル
#from sklearn.datasets import load_iris
#iris = load_iris()
#data_set = iris.data
#target_set =iris.target
gcforestの構築
mgc_forest = MGCForest(
estimators_config={
'mgs': [{
'estimator_class': ExtraTreesClassifier,
'estimator_params': {
'n_estimators': 30,
'min_samples_split': 21,
'n_jobs': -1,
}
}, {
'estimator_class': RandomForestClassifier,
'estimator_params': {
'n_estimators': 30,
'min_samples_split': 21,
'n_jobs': -1,
}
}],
'cascade': [{
'estimator_class': ExtraTreesClassifier,
'estimator_params': {
'n_estimators': 1000,
'min_samples_split': 11,
'max_features': 1,
'n_jobs': -1,
}
}, {
'estimator_class': ExtraTreesClassifier,
'estimator_params': {
'n_estimators': 1000,
'min_samples_split': 11,
'max_features': 'sqrt',
'n_jobs': -1,
}
}, {
'estimator_class': RandomForestClassifier,
'estimator_params': {
'n_estimators': 1000,
'min_samples_split': 11,
'max_features': 1,
'n_jobs': -1,
}
}, {
'estimator_class': RandomForestClassifier,
'estimator_params': {
'n_estimators': 1000,
'min_samples_split': 11,
'max_features': 'sqrt',
'n_jobs': -1,
}
}]
},
stride_ratios=[1.0 / 4, 1.0 / 9, 1.0 / 16],
)
%%time
skf = StratifiedKFold(n_splits=5,
shuffle=True,
random_state=0)
r_data = {}
steps = 1
for train_index, test_index in skf.split(data_set, target_set):
mgc_forest.fit(data_set[train_index,],target_set[train_index])
target_pred = mgc_forest.predict(data_set[test_index,])
r_data[steps] = {'test_accuracy': accuracy_score(target_set[test_index], target_pred),
'test_kappa': cohen_kappa_score(target_set[test_index], target_pred),
'test_blanced_accuracy': balanced_accuracy_score(target_set[test_index], target_pred),
'test_F1 score': f1_score(target_set[test_index], target_pred, average='weighted')
}
steps +=1
CPU times: user 13min 1s, sys: 27.4 s, total: 13min 28s
Wall time: 12min 37s
## Random forests の構築
model = RandomForestClassifier(random_state = 43,
n_jobs = -1,
n_estimators = 1000,
max_features = 'log2',
max_depth = None,
oob_score=False)
%%time
skf = StratifiedKFold(n_splits=5,
shuffle=True,
random_state=0)
rf_data = {}
steps = 1
for train_index, test_index in skf.split(data_set, target_set):
#print("分割されたデータセットの大きさ:{}".format(target_set[test_index].shape))
#print("分割される以前のデータセットのどこを抽出したのか?:{}".format(test_index))
#print("クラスラベル:{}".format(target_set[test_index]))
#print("クラスラベルの種類別個数{}".format( np.unique(target_set[test_index],return_counts=True)))
model.fit(data_set[train_index,],target_set[train_index])
target_pred = model.predict(data_set[test_index,])
rf_data[steps] = {'test_accuracy': accuracy_score(target_set[test_index], target_pred),
'test_kappa': cohen_kappa_score(target_set[test_index], target_pred),
'test_blanced_accuracy': balanced_accuracy_score(target_set[test_index], target_pred),
'test_F1 score': f1_score(target_set[test_index], target_pred, average='weighted')
}
steps +=1
CPU times: user 17.2 s, sys: 1.64 s, total: 18.9 s
Wall time: 8.61 s
結果
gcforestの精度
r_data
{1: {'test_accuracy': 0.582089552238806,
'test_kappa': 0.16357871792331324,
'test_blanced_accuracy': 0.5817326732673267,
'test_F1 score': 0.5799051338290626},
2: {'test_accuracy': 0.6119402985074627,
'test_kappa': 0.22363078142022386,
'test_blanced_accuracy': 0.6117821782178218,
'test_F1 score': 0.6115363902138791},
3: {'test_accuracy': 0.675,
'test_kappa': 0.35,
'test_blanced_accuracy': 0.675,
'test_F1 score': 0.6736210489317367},
4: {'test_accuracy': 0.6030150753768844,
'test_kappa': 0.20629070530620486,
'test_blanced_accuracy': 0.6031818181818182,
'test_F1 score': 0.6025936582952676},
5: {'test_accuracy': 0.6080402010050251,
'test_kappa': 0.21566447700859026,
'test_blanced_accuracy': 0.6077777777777778,
'test_F1 score': 0.6069481144323441}}
Random Forestsの精度
rf_data
{1: {'test_accuracy': 0.8507462686567164,
'test_kappa': 0.7014851485148514,
'test_blanced_accuracy': 0.8507425742574257,
'test_F1 score': 0.8507462686567164},
2: {'test_accuracy': 0.8159203980099502,
'test_kappa': 0.6317405298341173,
'test_blanced_accuracy': 0.8157920792079207,
'test_F1 score': 0.8157835867115555},
3: {'test_accuracy': 0.865,
'test_kappa': 0.73,
'test_blanced_accuracy': 0.865,
'test_F1 score': 0.8647260702923422},
4: {'test_accuracy': 0.8391959798994975,
'test_kappa': 0.6783838383838383,
'test_blanced_accuracy': 0.8391919191919192,
'test_F1 score': 0.8391959798994975},
5: {'test_accuracy': 0.8090452261306532,
'test_kappa': 0.6181579478893153,
'test_blanced_accuracy': 0.8091414141414142,
'test_F1 score': 0.8089873493553846}}
まとめ
- 小規模データセット(1000人, 110種類の質問)の精度
- Random Forestsの精度がgcForestよりも優れていた。
- 計算時間
- gcforest: 12min 37s
- Random Forests: 8.61 s
以上から、データに合わせて手法を選ぶべき、ということがわかる。
- 想像
- 訓練データへの精度は全て1.0であるため、データが少ないにも関わらず学習しすぎていることが、原因か?