目次 †
はじめに †
前回、Pythonの機械学習ライブラリーscikit-learnを用いて、決定木による分類を行いました。
- Pythonで決定木を使う - とうごろうぃき
前回はすべての説明変数を用いて予測モデルを学習しましたが、実際のデータに対する分析では、予測に不要な説明変数が含まれていることがあります。
また、説明変数が多すぎると、過学習 (Overfitting) が起こってしまい、予測モデルがうまく作れない(訓練データには適合するがテスト・データや検証用データには適合しない)ことがあります。
そこで、今回は、説明変数を減らす方法について説明します。
環境やデータは前回と同じです。
全体の流れ †
前回と同様に、TSVファイルを読み込んでデータフレームを作成します。
import pandas as pd df_iris_train = pd.read_csv('train.tsv', delimiter='\t', index_col=0) df_iris_test = pd.read_csv('test_X.tsv', delimiter='\t', index_col=0)
次に、予測モデルへの入力となる特徴行列 X と予測モデルからの出力ベクトル y を取り出します。
X = df_iris_train.drop('class', axis=1).values y = df_iris_train.class.values
ここで、特徴行列 X の列が多すぎるときに、特徴を減らします。 まず、特徴選択器を用意し、fit関数を用いて特徴行列 X(手法によっては特徴行列 X と出力ベクトル y)から特徴を減らすモデルを学習します。 次に、transform関数を用いて特徴行列 X を新しい特徴行列 X_ に変換します。 (次のプログラムが何をしているかについては後述します。)
from sklearn.feature_selection import SelectKBest fs = SelectKBest(k=3) fs.fit(X, y) X_ = fs.transform(X)
作成した特徴行列 X_ から予測モデルを学習します。
from sklearn.tree import DecisionTreeClassifier clf = DecisionTreeClassifier() clf.fit(X_, y)
テスト・データに適用する場合は、訓練データから学習した特徴を減らすためのモデルを用いて、transformだけを行います。
X = df_iris_test.values X_ = fs.transform(X) p = clf.predict(X_)
説明変数を減らす手法 †
説明変数を減らす手法としては、たくさんある説明変数(特徴、列)の中からいくつかの説明変数(特徴、列)を選択する特徴選択 (feature selection) を用いた方法と、次元数が大きい特徴行列から次元数が小さい特徴行列を生成する次元削減 (dimensionality reduction) を用いた方法があります。
特徴選択で選択された列は、元の特徴行列に含まれている列と同じですが、次元削減で生成された特徴行列の列は、元の特徴行列には含まれていません。
特徴選択 †
分散が小さい特徴を削除する †
分散が小さい特徴は出力に影響を与えにくいので、分散が閾値よりも小さい特徴を削除し、残った特徴を選択します。
from sklearn.feature_selection import VarianceThreshold fs = VarianceThreshold(threshold=1.0) fs.fit(X) X_ = fs.transform(X)
ここで、fsは特徴選択器を格納するための変数であり、feature selectorの略です。
単変量解析のスコアが低い特徴を削除する †
単変量解析を行って、スコアが低い特徴を削除し、残った特徴を選択します。
from sklearn.feature_selection import SelectKBest fs = SelectKBest(k=3) fs.fit(X, y) X_ = fs.transform(X)
ここで、k は選択する特徴の数です。 回帰問題の場合は、score_func オプションに 'f_regression' を指定します。
最も重要でない特徴を繰り返し削除する †
再帰的特徴削減 (Recursive Feature Elimination, RFE) という方法で、適切なサイズになるまで、最も重要でない特徴を一つずつ繰り返し削除し、残った特徴を選択します。 最も重要でない特徴を決めるために、学習器 estimator が必要です。
from sklearn.feature_selection import RFE from sklearn.svm import SVC est = SVC() fs = RFE(est, n_features_to_select=3) fs.fit(X, y) X_ = fs.transform(X)
ここでは、SVCを estimator として使っています。 n_features_to_select は選択する特徴の数です。
L1正則化を用いて特徴を削除する †
特徴に対する係数の絶対値が大きくなりすぎないようにペナルティを課す方法を正則化といい、L1正則化はかなり厳しいペナルティを課すことで係数をなるべくゼロにしてしまうというものです。 係数がゼロの特徴量はなくても構わないものなので、係数がゼロ以外の特徴を選択します。 L1正則化を行う学習器 estimator が必要です。
from sklearn.feature_selection import SelectFromModel from sklearn.svm import LinearSVC est = LinearSVC(penalty='l1') fs = SelectFromModel(est) fs.fit(X, y) X_ = fs.transform(X)
ここでは、線形SVCを estimator として使っています。
決定木学習を用いて特徴を選択する †
ランダム・フォレストのような決定木ベースの学習器を用いて学習を行い、重要と判定された特徴を選択します。 特徴の重要度 feature_importances_ を計算する学習器 estimator が必要です。
from sklearn.feature_selection import SelectFromModel from sklearn.ensemble import RandomForestClassifier est = RandomForestClassifier() fs = SelectFromModel(est) fs.fit(X, y) X_ = fs.transform(X)
ここでは、ランダム・フォレストを estimator として使っています。
次元削減 †
主成分分析を用いて次元を削減する †
主成分分析 (Principal Component Analysis, PCA) を用いて特徴を合成することによって、より次元数が小さい特徴空間を作ります。 PCAは、データ分析において特徴数が多いときに次元を圧縮するのに用いられるオーソドックスな方法です。
from sklearn.decomposition import PCA fs = PCA(n_components=3) fs.fit(X) X_ = fs.transform(X)
ここでは、合成後の次元数 n_components を 3 としています。
特異値分解を用いて次元を削減する †
特異値分解 (Singular Value Decomposition, SVD) を用いて特徴を合成することによって、より次元数が小さい特徴空間を作ります。 SVDは、制御理論の分野でノイズを含む環境でのロバストな制御を行うためにも用いられています。
from sklearn.decomposition import TruncatedSVD fs = TruncatedSVD(n_components=3) fs.fit(X) X_ = fs.transform(X)
ここでは、合成後の次元数 n_components を 3 としています。
独立成分分析を用いて次元を削減する †
独立成分分析 (Independent Component Analysis, ICA) を用いて特徴を合成することによって、より次元数が小さい特徴空間を作ります。 ICAは、音声認識の分野で混合信号を独立した成分に分解するのにも用いられています。
from sklearn.decomposition import FastICA fs = FastICA(n_components=3) fs.fit(X) X_ = fs.transform(X)
ここでは、合成後の次元数 n_components を 3 としています。
潜在的ディリクレ配分法を用いて次元を削減する †
潜在的ディリクレ配分法 (Latent Dirichlet Allocation, LDA) を用いて特徴を抽出することによって、より次元数が小さい特徴空間を作ります。 LDAは、自然言語処理の分野で文書からトピックを抽出するのにも用いられています。
from sklearn.decomposition import LatentDirichletAllocation fs = LatentDirichletAllocation(n_components=3) fs.fit(X) X_ = fs.transform(X)