ランダムフォレストで癌の良性・悪性を分類分類予測してみました。以前にChainerで同様の癌の分類問題を行ったので、比較してみたいと思います。
ランダムフォレストとは
ランダムフォレストは分類問題でよく用いられる手法です。ランダムフォレストは少しずつ異なる決定木という手法を集約させたものです。決定木は分類するために重要な説明変数や分類の過程がわかりやすいので、よく分類問題で用いられる手法ですが問題点があります。決定木には過剰適合しやすく汎化性能が低くなってしまう問題があります。過剰適合とは訓練データに対しては高い精度を出しますが、未知のテストデータに対しては高い精度を出すことができません。ランダムフォレストはこの決定木が過剰適合してしまうことに対する解決策の1つで、それぞれ異なった方向に過剰適合した決定木をたくさん作ってその平均を取れば過剰適合の度合いを減らし、決定木の予測性能を維持したまま汎化性能を高めるための方法です。つまり、ランダムフォレストとは過剰適合したモデルの平均をとって汎化性を高めた手法です。
ランダムフォレストのメリット・デメリット
分類アルゴリズムが複数ある中で、ランダムフォレストのメリットとデメリットをまとめました。
メリット
・汎化性が高い
・デフォルトのパラメータで十分よく機能する
・決定木同様にランダムフォレストでも特徴量の重要度をみることができる。
基本的に決定木の過剰適合してしまう欠点を補うためのアルゴリズムです。あえて決定木を使う場合があるとすれば、簡易な分類プロセスを可視化させたい場合だと言えます。
デメリット
・テキストデータなど非常に高次元のデータに対してうまく機能しない
・乱数のシード(random_state)を変更すると構築するモデルが大きく変わる
・メモリ消費量
・実行時間
テキストデータの分類や、メモリ消費量・実行時間が重要なアプリケーションには適さないように思います。
実装編
概要はこのくらいにして実際にランダムフォレストで顔の分類予測問題を解いてみたいと思います。
今回はランダムフォレストの便利関数で分類において重要な役割を果たしている説明変数を可視化し、モデルを再構築してみたいと思います。
・データの取得・加工
・説明変数・目的変数に分割
・訓練データ・テストデータ分割
・モデルの構築・予測
・重要な説明変数を確認
・重要なパラメータを活用してモデルの再構築
# library from sklearn.datasets import load_breast_cancer from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split import pandas as pd import numpy as np from matplotlib import pyplot as plt %matplotlib inline import seaborn as sns sns.set
データの取得・加工
cancer = load_breast_cancer() print(cancer.keys()) # Out dict_keys(['target_names', 'target', 'DESCR', 'feature_names', 'data'])
# function def get_target_names(x): if x == 0: return "malignant" if x == 1: return "benign"
cancer_data = pd.DataFrame(columns=cancer['feature_names'],data = cancer['data']) cancer_data['target'] = cancer['target'] cancer_data["target_names"] = cancer_data['target'].apply(lambda x : get_target_names(x)) cancer_data.head(5)
説明変数・目的変数に分割
X = cancer_data.iloc[:,0:30] y = cancer_data['target'] print("X shape:{}".format(X.shape)) print("y shape:{}".format(y.shape)) # Out X shape:(569, 30) y shape:(569,)
訓練データ・テストデータ分割
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=42)
モデルの構築・予測
forest = RandomForestClassifier(n_estimators=5, random_state=42) # n_estimators forest.fit(X_train,y_train) print("Accuracy on training set:{:.3f}".format(forest.score(X_train,y_train))) print("Accuracy on test set:{:.3f}".format(forest.score(X_test,y_test))) # Out Accuracy on training set:0.991 Accuracy on test set:0.958
パラメータのチューニングも行っていないのにかなり精度の高いモデルを構築できたのではないでしょうか?
Chainerと比較して見るとわかりやすいですが、パラメータチューニングなしだとChainerは訓練データに対して62%、テストデータに対して65%でした。
case-k.hatenablog.com
このようにランダムフォレストはデフォルトで十分な評価精度を算出することが可能です。
重要な説明変数を確認
def plot_feature_importances(model, X): n_features = X.shape[1] plt.barh(range(n_features), model.feature_importances_, align='center') plt.yticks(np.arange(n_features), X) plt.xlabel("Feature importance") plt.ylabel("Feature")
plot_feature_importances(forest, X)
分類問題で重要な説明変数を可視化できました。
説明変数「worst concave points」「 worst radius」「area error」
が分類予測において重要な役割を果たしているようです。
説明変数3つでモデルを再構築してみます。
重要なパラメータを活用してモデルの再構築
# function def get_feature_importances(model, X): feature_importances = pd.DataFrame() feature = X.keys() importances = model.feature_importances_ feature_importances['feature'] = feature feature_importances['importance'] = importances return feature_importances
関数を定義できましたので重要な説明変数を降順でみてみたいと思います。
df_feature_importances = get_feature_importances(forest, X) df_feature_importances_sort = df_feature_importances.sort_values(by='importance',ascending=False).head() df_feature_importances_sort.head()
重要とされる上位4つの説明変数を使ってモデルを再構築してみます。
columns = ['worst concave points','worst radius', 'area error','worst concavity'] X = cancer_data[columns] y = cancer_data['target'] X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=42) forest = RandomForestClassifier(n_estimators=5, random_state=42) # n_estimators forest.fit(X_train,y_train) print("Accuracy on training set:{:.3f}".format(forest.score(X_train,y_train))) print("Accuracy on test set:{:.3f}".format(forest.score(X_test,y_test))) # Out Accuracy on training set:0.993 Accuracy on test set:0.958
説明変数4つでテストデータに対して、説明変数30個分と同等の評価精度を確認できました。
このようにランダムフォレストは重要な説明変数を探索するのに適しています。
画像分類やテキストはディープラーニングのChainerが適しているように思いましたが、癌の分類予測問題はランダムフォレストの方が適しているように思いました。