決定木からランダムフォレストへ: ツリーベースアルゴリズムの原理と実装

決定木からランダムフォレストへ: ツリーベースアルゴリズムの原理と実装

この記事では、決定木の数学的詳細(およびさまざまな Python の例)とその長所と短所について説明します。内容はシンプルで、理解しやすいことがわかります。しかし、それらは一般的に、最良の教師あり学習法と比較すると競争力がありません。決定木のさまざまな欠点を克服するために、ブートストラップ集約やバギング、ランダム フォレストなどのさまざまな概念 (Python の例を使用) に焦点を当てます。広く使用されている別の持ち上げ方法については、後ほど別途説明します。それぞれのアプローチでは、複数のツリーを生成し、それらを組み合わせて単一の一貫した予測を生成するため、予測精度が大幅に向上することがよくあります。

決定木

決定木は教師あり学習アルゴリズムの一種です。これは、カテゴリ型と連続型の両方の入力 (特徴) および出力 (予測子) 変数で機能します。ツリーベースの方法では、特徴空間を一連の長方形に分割し、各長方形に単純なモデル (定数など) を割り当てます。概念的には、シンプルで効果的です。まず、例を通して決定木を理解しましょう。次に、正式な分析アプローチを使用して、意思決定ツリーを作成するプロセスを分析します。ローン会社の顧客に関する単純なデータセットを考えてみましょう。当社では、すべてのお客様に照会口座残高、信用履歴、勤続年数、以前のローン状況をお知らせしています。関連するタスクは、顧客のリスク レベルが信頼できるかどうかを予測することです。この問題は、次の決定木を使用して解決できます。

分類と回帰ツリー (略して CART) は、分類または回帰予測モデリングの問題を解決するために使用される決定木アルゴリズムを指すために Leo Breiman によって導入された用語です。多くの場合、scikit-learn を使用して決定木を生成および実装します。sklearn.tree.DecisionTreeClassifier と sklearn.tree.DecisionTreeRegressor を使用して、それぞれ分類ツリーと回帰ツリーを構築します。

CART モデル

CART モデルでは、適切なツリーが作成されるまで、入力変数とそれらの変数の分割ポイントを選択します。コスト関数を最小化するために、使用する入力変数と分割ポイントを選択するために貪欲アルゴリズムが使用されます。

ツリーの構築は、ツリー内の各リーフ ノードに割り当てられたトレーニング サンプルの最小数など、事前に定義された停止基準を使用して終了します。

その他の決定木アルゴリズム:

  • ID3: 反復二分法 3
  • C4.5: ID3アルゴリズムの改善
  • CHAID: カイ二乗自動相互作用検出器
  • MARS: 数値予測をより適切に処理するための決定木の拡張。
  • 条件付き推論ツリー

回帰ツリー

ここでは、回帰ツリーの CART アルゴリズムの詳細に焦点を当てます。つまり、意思決定ツリーの作成は次の 2 つのステップで構成されます。

1. 予測子空間、つまり可能な値のセット X_1、X_2、...、X_p を J 個の異なる重複しない領域 R_1、R_2、...、R_J に分割します。

2. 領域 R_J に入る各サンプル観測に対して同じ予測を行います。これは、R_J 内のトレーニング サンプルの予測の平均です。

J 領域 R_1、R_2、...、R_J を作成するために、予測領域は高次元の長方形またはボックスに分割されます。目的は、次の式でRSSを最小化できるボックス型領域R_1、R_2、...、R_Jを見つけることです。

ここで、yhat_Rjはj番目のボックス内のトレーニング観測の平均予測値です。

この空間分割は計算上不可能であるため、領域を分割するために再帰バイナリ分割と呼ばれる貪欲なアプローチがよく使用されます。

貪欲なのは、ツリーを構築するプロセスの各ステップで、将来を見据えて将来のステップに現れ、より良いツリーの構築に役立つ分割を選択するのではなく、各特定のステップで最適な分割が選択されるからです。すべての分割された領域 R_j は長方形であることに注意してください。再帰的バイナリセグメンテーションを実行するには、まず予測子X_jを選択し、カットポイントsを選択する。

ここで、yhat_R1は領域R_1(j,s)内の観測サンプルの平均予測値であり、yhat_R2は領域R_2(j,s)内の観測サンプルの予測平均です。このプロセスを繰り返して最適な予測子と分割ポイントを検索し、各サブ領域の RSS を最小化するためにデータをさらに分割します。ただし、予測子空間全体を分割するのではなく、以前に識別された 1 つまたは 2 つの領域のみを分割します。このプロセスは、停止基準に達するまで継続されます。たとえば、各領域に最大 m 個の観測サンプルが含まれるように停止基準を設定できます。領域 R_1、R_2、...、R_J を作成したら、テスト サンプルを指定して、領域内のすべてのトレーニング サンプルの平均予測値を使用してテスト サンプルの値を予測できます。

分類ツリー

分類ツリーは回帰ツリーと非常によく似ていますが、定量的ではなく定性的に応答を予測する点が異なります。上記から、回帰ツリーによって観測値に対して予測される連続値は、同じリーフノードに属するトレーニングサンプルの観測値の平均であることがわかります。ただし、分類ツリーの場合、予測するカテゴリは、特定の領域におけるトレーニング サンプル観測値の最も一般的なカテゴリ、つまりトレーニング観測値のモード応答になります。分類の目的を達成するために、システムは 1 つのカテゴリのみを予測するのではなく、カテゴリのグループとその発生確率を予測することがよくあります。

分類ツリーの生成は回帰ツリーの生成と非常に似ています。回帰ツリーと同様に、分類ツリーを生成するには一般的に再帰的なバイナリ分割を使用します。ただし、分類ツリーでは、RSS をバイナリ セグメンテーションの基準として使用することはできません。 RSS の代わりに、リーフ ノードの不純度尺度 Q_m を定義する必要があります。これは、サブセット領域 R_1、R_2、...、R_j 内のターゲット変数の均一性を測定できる方法です。ノード m では、N_m 個のサンプル観測値を使用して、領域 R_m 内のカテゴリの頻度を表すことができます。m 番目の領域における k 番目のカテゴリの頻度は次のように表すことができます。

ここで、I(y_i=k) は指示関数です。つまり、y_i = k の場合は 1、それ以外の場合は 0 になります。

不純物 Q_m を測定するより自然な方法は、分類エラー率です。分類エラー率は、トレーニング観測が領域内で最も一般的なクラスに属していない確率を表します。

この関数は微分可能ではないため、数値的に最適化することはできません。さらに、この関数はノード確率の変化に敏感ではないため、この分類エラー率はツリーの成長に非常に非効率的です。通常、ノードのエラー メトリックを測定するには、ジニ インデックスとクロス エントロピー関数を使用します。

ジニ係数は k 個のカテゴリの合計分散を測定し、通常は次のように定義されます。

ジニ指数値が小さいほど、ノードに特定のカテゴリのサンプル観測値のほとんどが含まれていることを示します。

情報理論では、クロスエントロピー関数はシステム内のカオスの度合いを測定するために使用されます。バイナリ システムの場合、システムに 1 つのカテゴリのすべての要素が含まれている場合、その値は 0 になり、カテゴリの数が同じ場合、クロス エントロピーは最大の 1 に達します。したがって、ジニ指数と同様に、クロスエントロピー関数もノードの不純度を測定するために使用できます。

G と同様に、S の値が小さいほど、領域内のノードに単一のカテゴリの観測値が最も多く含まれていることを示します。

決定木の一般的なパラメータと概念

決定木を数学的に理解したい場合、まず決定木とツリー学習アルゴリズムの一般的な概念を理解する必要があります。次の用語を理解することは、モデルの調整にも役立ちます。

  • ルート ノード: すべてのデータ サンプルを表す親ノードであり、さらに 2 つ以上の子ノードに分割できます。
  • 分割: ノードを 2 つ以上のサブノードに分割するプロセス。
  • 決定ノード: サブノードをさらに複数のサブノードに分割できる場合、そのノードは決定ノードと呼ばれます。
  • リーフ/ターミナル ノード: それ以上分割されず、分類ツリー内のカテゴリを表すノード。
  • ブランチ/サブツリー: 意思決定ツリー全体の一部。
  • 親ノードと子ノード: ノードが下方向に分割される場合、そのノードは親ノードと呼ばれ、親ノードから分割されたノードは子ノードと呼ばれます。
  • ノード分割の最小サンプル数: ノード分割に必要な最小サンプル数 (または観測値)。この方法は、過剰適合を防ぐためによく使用されます。サンプルの最小数を大きくすると、モデルが特定のサンプルに対して過度に具体的な関係を学習するのを防ぐことができます。このハイパーパラメータは、検証セットを使用して調整する必要があります。
  • リーフ ノードの最小サンプル数: リーフ ノードに必要な最小サンプル数。ノード分割の最小サンプル数と同様に、このハイパーパラメータはオーバーフィッティングを制御するためにも使用できます。不均衡なクラスの問題の場合、少数クラスに属するサンプルの数が非常に少ない可能性があるため、より小さな値を取る必要があります。
  • ツリーの最大深度 (垂直深度): このハイパーパラメータは、オーバーフィッティングの問題を制御するためにも使用できます。深度を小さくすると、モデルが特定のサンプルに対して過度に具体的な関係を学習するのを防ぐことができます。このハイパーパラメータは、検証セットでも調整する必要があります。
  • リーフ ノードの最大数: リーフ ノードの最大数は、最大深度設定を置き換えることができます。深さ n の二分木は最大 2^n 個のリーフ ノードを生成できるためです。
  • 分割に考慮する必要がある特徴の最大数: つまり、より優れた分離ソリューションを探すときに考慮する必要がある特徴の数です。一般的な方法は、利用可能な特徴の合計数の平方根を最大特徴数として取ることです。

分類ツリーの実装

上記のさまざまな決定木モデルを説明するために、Kaggle.com からダウンロードできる Kaggle の米国所得データセットを使用します。次のコードは、インポート プロセスとデータセットのコンテンツの一部を示しています。

pandasをpdとしてインポートする
numpyをnpとしてインポートする
plotnine からのインポート *
matplotlib.pyplot を plt としてインポートします。
sklearn.preprocessing から LabelEncoder をインポートします
sklearn_pandasからDataFrameMapperをインポートします
sklearn.tree から DecisionTreeClassifier をインポートします
sklearn.ensemble から RandomForestClassifier をインポートします

トレーニングデータ = './adult-training.csv'
テストデータ = './adult-test.csv'

columns = ['年齢','労働階級','fnlgwt','教育','EdNum','婚姻状況','職業','関係','人種','性別','資本増加','資本減少','週あたりの労働時間','国','収入']

df_train_set = pd.read_csv(トレーニングデータ、名前=列)
df_test_set = pd.read_csv(test_data、名前=列、スキップ行=1)
df_train_set.drop('fnlgwt', 軸=1, インプレース=True)
df_test_set.drop('fnlgwt', 軸=1, インプレース=True)

上記のコードでは、まず必要なライブラリとモジュールをすべてインポートし、データと構造をトレーニング データと検証データに読み込む必要があります。この行はモデルのトレーニングには重要ではないため、fnlgwt 列も削除します。

トレーニング データの最初の 5 行を表示するには、次のステートメントを入力します。

df_train_set.head()

以下に示すように、データのクリーニングも行う必要があります。列からすべての特殊文字を削除する必要があり、スペースや「.」も削除する必要があります。

#df_train_set.columns の i の特殊文字を「不明」に置き換えます。
    df_train_set[i].replace(' ?', '不明', inplace=True)
    df_test_set[i].replace(' ?', 'Unknown', inplace=True) df_train_set.columns 内の col:if df_train_set[col].dtype != 'int64':
        df_train_set[col] = df_train_set[col].apply(lambda val: val.replace(" ", ""))
        df_train_set[col] = df_train_set[col].apply(lambda val: val.replace(".", ""))
        df_test_set[col] = df_test_set[col].apply(lambda val: val.replace(" ", ""))
        df_test_set[col] = df_test_set[col].apply(lambda val: val.replace(".", ""))

上の画像でわかるように、個人の教育歴を表す 2 つの行があります: Eduction と EdNum。これら 2 つの特徴は高い相関関係にあると想定されるため、Education 列を削除できます。国列は収入の予測には役立たないので、削除する必要があります。

df_train_set.drop(["国", "教育"], axis=1, inplace=True)
df_test_set.drop(["国", "教育"], axis=1, inplace=True)

Age 列と EdNum 列は数値です。連続した数値データを、年齢を 10 年の倍数に、教育年数を 5 年の倍数に変更するなど、より効率的な方法に変換できます。実装コードは次のとおりです。

列名 = リスト(df_train_set.列)
colnames.remove('年齢')
列名を削除します('EdNum')
colnames = ['年齢グループ', '教育'] + colnames

ラベル = ["{0}-{1}".format(i, i + 9)、i は範囲(0, 100, 10)]
df_train_set['AgeGroup'] = pd.cut(df_train_set.Age、範囲(0、101、10)、右=False、ラベル=ラベル)
df_test_set['AgeGroup'] = pd.cut(df_test_set.Age、範囲(0、101、10)、右=False、ラベル=ラベル)

ラベル = ["{0}-{1}".format(i, i + 4)、i は範囲(0, 20, 5)]
df_train_set['教育'] = pd.cut(df_train_set.EdNum、範囲(0、21、5)、右=False、ラベル=ラベル)
df_test_set['教育'] = pd.cut(df_test_set.EdNum、範囲(0、21、5)、右=False、ラベル=ラベル)

df_train_set = df_train_set[列名]
df_test_set = df_test_set[列名]

データのクリーンアップが完了したので、次のステートメントでデータの概要を表示できます。

df_train_set.Income.value_counts()
<=50K 24720
>50K 7841
名前: 収入、データ型: int64
df_test_set.Income.value_counts()
<=50K 12435
>50K 3846
名前: 収入、データ型: int64

トレーニング セットとテスト セットの両方で、50K を超えるクラスよりも 50K 以下のクラスが 3 倍多いことがわかりました。ここから、サンプル データはバランスの取れたデータではないことがわかりますが、ここでは問題を単純化するために、データ セットを通常の問題として扱います。

電気通信

ここで、トレーニング データ内のさまざまな特徴の分布と相互依存性をグラフの形で見てみましょう。まず、Relationships 機能と MaritalStatus 機能がどのように相互に関連しているのかを見てみましょう。

(ggplot(df_train_set, aes(x = "Relationship", fill = "MaritalStatus"))+ geom_bar(position="fill")+ theme(axis_text_x = element_text(angle = 60, hjust = 1)))

まず、年齢層ごとに教育が収入(就学年数で測定)に与える影響を見てみましょう。

(ggplot(df_train_set, aes(x = "教育", fill = "収入"))+ geom_bar(position="fill")+ theme(axis_text_x = element_text(angle = 60, hjust = 1))+ facet_wrap('~AgeGroup'))

最近、性別が所得格差に与える影響について多くの議論がなされています。教育レベルと人種の影響は、男性と女性で別々に見ることができます。

(ggplot(df_train_set, aes(x = "教育", fill = "収入"))+ geom_bar(position="fill")+ theme(axis_text_x = element_text(angle = -90, hjust = 1))+ facet_wrap('~性別'))

(ggplot(df_train_set, aes(x = "人種", fill = "所得"))+ geom_bar(position="fill")+ theme(axis_text_x = element_text(angle = -90, hjust = 1))+ facet_wrap('~性別'))

これまでは、非数値特徴間の関係性にのみ焦点を当ててきました。それでは、キャピタルゲインとキャピタルロスが所得に与える影響を見てみましょう。

(ggplot(df_train_set, aes(x="Income", y="CapitalGain"))+ geom_jitter(position=position_jitter(0.1)))

(ggplot(df_train_set, aes(x="Income", y="CapitalLoss"))+ geom_jitter(position=position_jitter(0.1)))

ツリー分類器

データ内のいくつかの関係を理解し​​たので、 sklearn.tree.DecisionTreeClassifier を使用して単純なツリー分類モデルを作成できます。ただし、このモデルを使用するには、すべての非数値データを数値データに変換する必要があります。 sklearn.preprocessing.LabelEncoder モジュールと sklearn_pandas モジュールを使用して、Pandas データ フレーム内でこれを直接簡単に実行できます。

マッパー = DataFrameMapper([('AgeGroup', LabelEncoder()),('Education', LabelEncoder()),('Workclass', LabelEncoder()),('MaritalStatus', LabelEncoder()),('Occupation', LabelEncoder()),('Relationship', LabelEncoder()),('Race', LabelEncoder()),('Sex', LabelEncoder()),('Income', LabelEncoder())], df_out=True、デフォルト=None)

列 = リスト(df_train_set.列)
cols.remove("収入")
cols = cols[:-3] + ["収入"] + cols[-3:]

df_train = mapper.fit_transform(df_train_set.copy())
df_train.columns = 列

df_test = mapper.transform(df_test_set.copy())
df_test.columns = 列

cols.remove("収入")
x_train、y_train = df_train[cols].values、df_train["収入"].values
x_test、y_test = df_test[cols].values、df_test["収入"].values

トレーニング データとテスト データが正しい形式で用意できたので、最初のモデルが作成されました。

ツリー分類子 = 決定ツリー分類子()
ツリー分類器.fit(x_train, y_train)
ツリー分類器.スコア(x_test, y_test)

最適化されていない最も単純な確率分類モデルは、83.5% の精度を達成できます。分類問題では、混同行列はモデルの精度を測定するのに適した方法です。次のコードを使用すると、任意のツリーベース モデルの混同行列をプロットできます。

itertools をインポートします。sklearn.metrics をインポートします。confusing_matrixdef plot_confusion_matrix(cm, classes, normalize=False):"""
    この関数は混同行列を印刷してプロットします。
    `normalize=True` を設定することで正規化を適用できます。
    「」
    cmap = plt.cm.Blues
    title = "混同行列"正規化する場合:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
        cm = np.around(cm, 小数点以下3)

    plt.imshow(cm, 補間='最も近い', cmap=cmap)
    plt.title(タイトル)
    plt.カラーバー()
    tick_marks = np.arange(len(クラス))
    plt.xticks(目盛り、クラス、回転=45)
    plt.yticks(目盛り、クラス)

    thresh = cm.max() / 2.itertools.product(range(cm.shape[0]), range(cm.shape[1]))内のi、jについて:
        plt.text(j, i, cm[i, j],
                 水平配置="中央",
                 color="white"(cm[i, j] > threshの場合)、それ以外は"black")

    plt.tight_layout()
    plt.ylabel('真のラベル')
    plt.xlabel('予測ラベル')

ここで、最初のモデルの混同行列を見てみましょう。

y_pred = ツリー分類器.予測(x_test)
cfm = 混乱行列(y_test, y_pred, ラベル=[0, 1])
plt.figure(図サイズ=(10,6))
plot_confusion_matrix(cfm、クラス=["<=50K", ">50K"]、正規化=True)

多数派クラス (<=50K) の精度は 90.5% であるのに対し、少数派クラス (>50K) の精度はわずか 60.8% であることがわかりました。

この単純な分類器を調整する方法を見てみましょう。 5 段階のクロス検証を備えた GridSearchCV() を使用して、ツリー分類器のさまざまな重要なパラメータを調整できます。

sklearn.model_selection から GridSearchCV をインポートします
パラメータ = {'max_features':(なし、9、6)、'max_depth':(なし、24、16)、'min_samples_split': (2、4、8)、'min_samples_leaf': (16、4、12)}

clf = GridSearchCV(treeClassifier、パラメータ、cv=5、n_jobs=4)
clf.fit(x_train, y_train)
clf.best_score_、clf.score(x_test、y_test)、clf.best_params_
(0.85934092933263717、
0.85897672133161351、
{'最大深度': 16,
'最大機能': 9,
'最小サンプル数': 16,
'min_samples_split': 8})

最適化後、精度が 85.9% に向上したことがわかりました。上記では、最適モデルのパラメータも確認できます。それでは、最適化されたモデルの混同行列を見てみましょう。

y_pred = clf.predict(x_test)
cfm = 混乱行列(y_test, y_pred, ラベル=[0, 1])
plt.figure(図サイズ=(10,6))
plot_confusion_matrix(cfm、クラス=["<=50K", ">50K"]、正規化=True)

最適化後、両方のカテゴリで予測精度が向上したことがわかりました。

決定木の限界

決定木には次のような多くの利点があります。

  • 理解しやすく説明しやすい
  • 視覚化
  • 大規模なデータ準備は必要ありません。ただし、sklearn.tree モジュールは欠損値をサポートしていないことに注意してください。
  • 決定木 (データの予測) を使用するコストは、決定をトレーニングするために使用されるデータの対数です。

しかし、これらのモデルは直接使用されることはあまりありません。決定木の一般的な欠点は次のとおりです。

  • 構築されたツリーは複雑すぎるため、データを適切に一般化できません。
  • データに小さな変更を加えると、まったく異なるツリーが生成される可能性があるため、決定木は十分に安定していません。
  • 実際には、決定木学習アルゴリズムは通常、貪欲アルゴリズムなどのヒューリスティック アルゴリズムに基づいて、各ノードでローカルに最適な決定を下します。このようなアルゴリズムでは、グローバルに最適な決定木を返すことを保証できません。
  • 特定のクラスが優勢になると、決定木学習者によって構築された決定木に偏りが生じます。したがって、決定木に適合させる前にデータセットのバランスをとることが推奨されます。
  • XOR、パリティ、マルチプレクサなどの特定のクラスの関数は、決定木モデルを使用してモデル化するのが困難です。

これらの制限のほとんどは、意思決定ツリーを改善することで簡単に対処できます。以下では、バギングとランダムフォレストに焦点を当てて、いくつかの関連する概念を紹介します。

剪定

決定木はデータに過剰適合する傾向があるため、枝の少ない小さな木(つまり、面積 R_1、…、R_J が縮小された木)はバイアスがわずかに高くなりますが、分散が低くなり、解釈しやすくなります。上記の問題に対処する 1 つの方法は、リーフ ノードのエラー率 Qm が特定の (高い) しきい値を超えて減少すると各ブランチが終了するツリーを構築することです。しかし、分割アルゴリズムの貪欲な性質により、実際には近視眼的になります。意思決定ツリーの初期段階では一見役に立たない分割が、後になって優れた分割につながり、Qm が大幅に低下する可能性があります。

したがって、より良い戦略は、非常に大きなツリー T_0 を構築し、それを剪定してサブツリーを取得することです。剪定に使用できる戦略は多数あります。コスト複雑性プルーニング (最弱リンクプルーニングとも呼ばれる) は、効果的な戦略の 1 つです。考えられるすべてのサブツリーを考慮することに加えて、非負のチューニングパラメータ α によってインデックス付けされたツリーのシーケンスも考慮する必要があります。 α の各値は、可能な限り小さいサブツリー T⊂T_0 に対応します。

ここで、|T| はツリー T 内のリーフ ノードの数を表し、R_m は m 番目のリーフ ノードに対応する長方形 (予測子空間のサブセット) を表し、yhat_Rm は Rm の予測値、つまり Rm 内のトレーニング サンプルの予測値の平均 (または分類ツリー内のモード応答) です。パラメータ α を調整して、サブツリーの複雑さとトレーニング データの適合との間のトレードオフを制御します。 α= 0 の場合、サブツリー T は T_0 と同等です。 α の値が大きくなるにつれて、複数の子ノードを持つツリーを構築するコストが高くなるため、上記の式は最小化され、より小さなサブツリーが得られます。ある種のクロスバリデーション法を使用して、剪定パラメータ α を選択できます。

現在、sklearn.tree 決定木分類器 (および回帰器) はプルーニングをサポートしていないことに注意してください。

ブートストラップ集約(バギング)

統計学において、ブートストラップとは、復元抽出によるランダムサンプリングに依存するテストまたは測定を指します。上記から、決定木は大きな変動の影響を受けることがわかります。つまり、トレーニング データをランダムに 2 つの部分に分割し、両方に決定木を当てはめると、得られる結果がかなり異なる可能性があります。ブートストラップ クラスタリング、またはバギングは、統計学習方法の分散を減らすための一般的な手順です。

それぞれ分散 *σ^*2 を持つ n 個の独立したサンプル観測値 Z_1、Z_2、...、Z_n のセットが与えられた場合、サンプル観測値の平均分散は *σ^*2/*n* です。言い換えれば、観測値のグループを平均すると、分散が減少します。したがって、分散を減らし、統計学習法の予測精度を高める自然な方法は、母集団から多くのトレーニング セットを取得し、各トレーニング セットを使用して個別の予測モデルを作成し、予測を平均することです。

ここでの問題は、複数のトレーニング データセットを取得できないことです。代わりに、(単一の)トレーニング データセットから繰り返しサンプルを取得してブートストラップすることができます。このアプローチでは、B 個の異なるブートストラップ トレーニング データセットを生成します。次に、b 番目のブートストラップ データセットの予測を取得し、集計予測を取得します。

これをバギングといいます。回帰問題と分類問題では集計方法が異なる場合があることに注意してください。予測を平均化することは回帰問題ではうまく機能しますが、分類問題における集約メカニズムにより、全体的な予測は B 予測の中で最も頻繁に発生するメインクラスとなるため、多数決を使用する必要があります。

アウトオブバッグ(OOB)エラー

Bagging 法の最大の利点は、クロス検証なしでテスト エラーを取得できることです。バギング法の本質は、複数のツリーを観測値のブートストラップされたサブセットに繰り返し適合させることができることであるということを思い出してください。平均して、袋詰めされた各木は観察サンプルの 2/3 を利用できます。残りの 1/3 の観測値は、out-of-bag (OOB) 観測値と呼ばれ、指定された bagged ツリーに適合しません。各ツリーからの OOB 観測値を使用して i 番目の観測値の予測を計算することができ、その結果、i 番目の観測値に対して約 B/3 の予測値が得られます。これで、バギングに似たクラスタリング手法 (平均回帰と多数決分類) を使用でき、i 番目の観測値に対して単一の予測を得ることができます。このようにして、n 個の観測値に対する OOB 予測を取得できるため、全体的な OOB MSE (回帰問題の場合) と分類エラー率 (分類問題の場合) を計算できます。 OOB エラー結果は、各例の予測値がトレーニング モデルの適合に使用されなかった例のみを使用して作成されるため、バギング モデルのテスト エラーの有効な推定値となります。

機能の重要度測定

通常、単一のツリーを使用することで、バギングによって予測の精度が向上します。ただし、最終モデルの解釈は難しい場合があります。多数のツリーをバギングすると、単一のツリーを使用して最終的な統計学習プロセスを表すことはできなくなります。そのため、バギングによって解釈可能性が犠牲になって予測精度が向上します。興味深いことに、RSS (回帰ツリーのバギング用) またはジニ指数 (分類ツリーのバギング用) を使用して、各予測子の全体的な概要を取得できます。バギング回帰ツリーの場合、すべての B ツリーにわたって平均化された特定の予測子分子の分割による RSS 削減の合計量を記録できます。値が大きいほど、重要な予測因子であることを示します。同様に、バギング分類ツリーの場合、すべての B ツリーにわたって平均化された特定の予測子分子分割によるジニ指数の減少をすべて追加できます。トレーニングが完了すると、sklearn モジュールのさまざまなバッグド ツリー学習方法により、属性として特徴の重要度データに直接アクセスできるようになります。

ランダムフォレストモデル

バギングは分散を減らすことで一般的な決定木の予測性能を向上させますが、他の欠点もあります。バギングではブートストラップされたサンプルで木全体を成長させる必要があり、計算の複雑さが B 倍に増加します。さらに、バギングに基づくツリーは相関しているため、予測精度は B に従って飽和します。

ランダム フォレストは、ランダムな摂動によってすべてのツリーの相関関係を解消するため、ランダム フォレストはバギングよりも優れたパフォーマンスを発揮します。バギングとは異なり、ランダム フォレストでは、各ツリーを構築するときに、各ノードが分割される前にランダム サンプル予測子を使用します。ランダムフォレストは本質的にはバギングツリーと同じなので、分散が少なくなります。さらに、ランダム フォレストでは、多数の予測子を使用することを検討できます。これは、このアプローチによってバイアスが軽減されるだけでなく、ローカル機能予測子がツリー構造での意思決定において重要な役割を果たすためです。

ランダム フォレストでは、観測数よりも多くの膨大な数の予測子を使用できます。ランダム フォレスト メソッドを使用する最大の利点は、適合値と推定セグメンテーションのバイアスを減らすために、より多くの情報を取得できることです。

多くの場合、平均的なパフォーマンスが他の競合する予測子よりも一貫して優れているため、決定木フィッティング プロセスを支配する予測子がいくつかあります。したがって、ローカル データ機能に役立つ他の多くの予測子は、分割変数として選択されません。ランダム フォレストが十分な数の決定木モデルを計算すると、各予測子が分割を定義する予測子になる可能性が少なくともいくつかあります。ほとんどの場合、優勢な予測子だけでなく、特徴予測子もデータセットの分割を定義する機会があります。

ランダム フォレストを調整するための主なハイパーパラメータは 3 つあります。

  • ノード サイズ: 決定木とは異なり、ランダム フォレストではリーフ ノードあたりの観測値が非常に少なくなる場合があります。このハイパーパラメータの目的は、ツリーを成長させるときに偏差をできるだけ小さく保つことです。
  • 木の数: 実際には、数百本の木が一般的に適切な選択です。
  • サンプルされた予測子の数: 一般的に、合計 D 個の予測子がある場合、回帰タスクのサンプル数として D/3 個の予測子を使用し、分類タスクのサンプル数として D^(1/2) 個の予測子を使用できます。

ランダムフォレストモデルの例

上記と同じ収入データを使用して、500 本のツリーを持つ単純なランダム フォレスト分類モデルを構築します。

rclf = ランダムフォレスト分類器(n_estimators=500)
rclf.fit(x_train, y_train)
rclf.score(x_test, y_test)

最適化を行わなくても、モデルのパフォーマンスは最適化された決定木分類器に匹敵し、テスト スコアは 85.1% に達することがわかります。以下の混同行列によると、単純ランダムフォレストと最適化されたツリー分類器のパフォーマンスは同様に、多数派クラス (収益 <= 50K) で 92.1%、少数派クラス (収益 > 50K) で 62.6% の予測精度を達成していることがわかります。

rclf = ランダムフォレスト分類器(n_estimators=500)
rclf.fit(x_train, y_train)
rclf.score(x_test, y_test)

前述したように、ランダム フォレスト モデルは特徴の重要度の尺度も提供します。現在のモデルのさまざまな機能の重要性は、以下の図で確認できます。

重要度 = rclf.feature_importances_
インデックス = np.argsort(重要度)
cols = [cols[x] (インデックス内の x の場合)]
plt.figure(図サイズ=(10,6))
plt.title('機能の重要性')
plt.barh(範囲(len(インデックス)), 重要度[インデックス], color='b', align='center')
plt.yticks(範囲(長さ(インデックス)), 列数)
plt.xlabel('相対的重要度')

ここで、ランダム フォレスト モデルの最適化を試みます。次のように、5 分割クロス検証を伴う GridSearchCV() 操作を使用して、ランダム フォレストを最適化できます。

パラメータ = {'n_estimators':(100, 500, 1000),'max_depth':(なし, 24, 16),'min_samples_split': (2, 4, 8),'min_samples_leaf': (16, 4, 12)}

clf = GridSearchCV(RandomForestClassifier(), パラメータ, cv=5, n_jobs=8)
clf.fit(x_train, y_train)
clf.best_score_、clf.best_params_
0.86606676699118579
{'最大深度': 24,
 '最小サンプル数': 4,
 '最小サンプル分割': 4,
 'n_estimators': 1000}
0.86606676699118579
{'最大深度': 24,
'最小サンプル数': 4,
'最小サンプル分割': 4,
'n_estimators': 1000}

現在のモデルは予測率が 86.6% で、以前のモデルよりも大幅に優れていることがわかります。以下の混同行列によると、新しいモデルでは多数派クラスの予測精度が大幅に向上し、少数派クラスの精度はわずかに低下しただけです。これは、不均衡なデータの一般的な問題です。

rclf2 = randomforestclassifier(n_estimators = 1000、max_depth = 24、min_samples_leaf = 4、min_samples_split = 8)
rclf2.fit(x_train、y_train)

y_pred = rclf2.predict(x_test)
cfm = cuspry_matrix(y_test、y_pred、labels = [0、1])
plt.figure(figsize =(10,6))
plot_confusion_matrix(cfm、classes = ["<= 50k"、 "> 50k"]、remormize = true)

最後に、最適化されたモデルにとって重要な機能を以下に示します。

Importances = rclf2.feature_importances_
indices = np.argsort(Importances)
cols = [インデックスのxのcols [x]]
plt.figure(figsize =(10,6))
plt.title( '機能の重要性')
plt.barh(range(len(indices))、imvertances [indices]、color = 'b'、align = 'center')
plt.yticks(range(len(indices))、cols)
plt.xlabel( '相対的な重要性')

ランダムな森林の制限

袋詰めの木モデルの一般的な制限に加えて、ランダムフォレストにはいくつかの制限があります。

  • 範囲外の独立した変数または従属変数を推測する必要がある場合、ランダムな森林はうまくいきません。火星のようなアルゴリズムを使用する方が良いでしょう。
  • ランダムフォレストアルゴリズムは、トレーニングと予測の両方で遅いです。
  • 区別すべき多くのカテゴリがある場合、ランダムフォレストはうまく機能しません。

一般に、ランダムフォレストは一般に、多くのタスクでのブースト方法よりも正確ではなく、実行に時間がかかります。すべてのKaggleコンペティションでは、多くのモデルが勾配ブーストツリーアルゴリズムまたはその他の優れたブースト方法を使用しています。

<<:  知っておくべきビッグデータ用語 75 選

>>:  図解機械学習: ニューラルネットワークと TensorFlow によるテキスト分類

ブログ    
ブログ    

推薦する

C# の敏感な単語フィルタリング アルゴリズムの実装

この記事はWeChatの公開アカウント「UP Technology Control」から転載したもの...

...

世界を変える 7 つの AI アプリケーション | Frontier Exploration

カリフォルニア大学サンディエゴ校で開発・実装されている AI 主導のテクノロジーとイノベーションの多...

企業、不動産会社、自動車会社が顔情報を収集する方法を弁護士が解説:消費者は法律に従って権利を断固として守るべき

[[388553]] 3月18日夜、企業やメーカーが個人情報を不法に収集し、商業目的で利用する事件が...

金融業界は AI を活用してデータを強化する準備ができているでしょうか?

金融業界は国民経済の生命線です。モバイルインターネットやオンライン決済の普及により、データは企業にと...

人工知能、機械学習、ディープラーニングとは、いったい何なのでしょうか?

近年のホットな言葉といえば、「人工知能」が挙げられます。昨年のChatGPTの人気爆発により、「AI...

AIが「テクノロジー冬季オリンピック」を支援、UBTECHロボティクスが氷と雪の世界に進出

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

ドローンはサメに対する私たちの考え方を変えている、と研究で判明

Google で「サメ」と検索すると、サメ​​の目撃情報に関する最近のニュースの見出しがいくつか表示...

アリババが雲奇会議でデジタル経済について語らなかったこと

2009 年以来、雲奇会議は、最も初期のローカル ウェブサイト サミットから、アリババの年次戦略およ...

2021年:AIが普及する年

リン・ジエル科学技術の継続的な進歩と発展に伴い、人工知能の発展は時代の必然的な流れであり、我が国の経...

...

人工知能搭載の携帯電話は私たちの生活をどのように変えるのでしょうか? 携帯電話メーカーが何をしてきたか見てみましょう。

チャットができる「インテリジェント音声アシスタント」から、さまざまな家電を操作できるスマートスピーカ...

...

...

考えてみましょう: なぜ AI が必要ないのでしょうか?

[[270404]] [51CTO.com クイック翻訳] 人工知能(AI)は今ホットな話題であり...