ドキュメンテーション センター

  • 評価版
  • 製品アップデート

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

アンサンブル法

アンサンブル学習のフレームワーク

多くの弱学習器の結果を精度の高い 1 つの集団予測子に結合するには、いくつかの方法があります。これらのメソッドは同じ構文に忠実に従っているため、コマンドで別のメソッドを試す場合でもわずかな変更で済みます。

関数 fitensemble で集団を作成します。構文は、次のようになります。

ens = fitensemble(X,Y,model,numberens,learners)
  • X は、データの行列です。各行には 1 つの観測値、各列には 1 つの予測子変数が含まれます。

  • Y は応答のベクトルで、X の行で表される観測値の数と同じ数になります。

  • model は集団のタイプを表す名前の文字列です。

  • numberens は、learners の各要素にある ens の弱学習器の数です。そのため、ens の要素数は、learners の要素数を numberens 倍した数になります。

  • learners は、弱学習器の名前を表す文字列、弱学習器のテンプレートまたはそのようなテンプレートのセル配列のいずれかです。

集団を作成するために必要な情報を図で示します。

分類または非線形回帰の問題では、次の手順を実行して集団を作成します。

  1. 行列への予測データの設定

  2. 応答データの準備

  3. 適用するアンサンブル法の選択

  4. 集団メンバー数の設定

  5. 弱学習器の準備

  6. fitensemble の呼び出し

行列への予測データの設定

どの教師あり学習の方式であっても、このドキュメンテーションでは通常 X と表記されているデータ行列から開始されます。X の各行が、1 つの観測値を表します。X の各列が、1 つの変数または予測子を表します。

応答データの準備

応答データには、さまざまなデータ型を使用できます。

  • 回帰集団の場合、YX の行数と同じ数の要素をもつ数値ベクトルでなければなりません。

  • 分類集団の場合、Y には、次の表に示す任意のデータ型を使用できます。この表では、欠損値を表現する方法も示しています。

    データ型欠損値
    数値ベクトルNaN
    カテゴリカル ベクトル<undefined>
    文字配列空白行
    文字列のセル配列''
    論理ベクトル(表現されない)

    fitensemble は、集団を作成するときに、Y の欠損値は無視します。

たとえば、応答データに 3 つの観測、truefalsetrue がこの順序で含まれているとします。この場合、Y は次のように表現できます。

  • [1;0;1] (数値ベクトル)

  • nominal({'true','false','true'}) (カテゴリカル ベクトル)

  • [true;false;true] (論理ベクトル)

  • ['true ';'false';'true '] (各行が同じ長さになるように空白が埋め込まれた、文字配列)

  • {'true','false','true'} (文字列のセル配列)

最も適切なデータ型を使用してください。欠損値は論理エントリでは表現できないため、Y に欠損値が存在するときには論理エントリは使用しないでください。

適用するアンサンブル法の選択

fitensemble は、次のいずれかのアルゴリズムを使用して集団を作成します。

  • 2 つのクラスによる分類:

    • 'AdaBoostM1'

    • 'LogitBoost'

    • 'GentleBoost'

    • 'RobustBoost' (Optimization Toolbox™ のライセンスが必要)

    • 'LPBoost' (Optimization Toolbox のライセンスが必要)

    • 'TotalBoost' (Optimization Toolbox のライセンスが必要)

    • 'RUSBoost'

    • 'Subspace'

    • 'Bag'

  • 3 つ以上のクラスによる分類:

    • 'AdaBoostM2'

    • 'LPBoost' (Optimization Toolbox のライセンスが必要)

    • 'TotalBoost' (Optimization Toolbox のライセンスが必要)

    • 'RUSBoost'

    • 'Subspace'

    • 'Bag'

  • 回帰:

    • 'LSBoost'

    • 'Bag'

'Bag' はすべてのメソッドに適用されます。'Bag' を使用する場合、type の名前と値のペアを 'classification' または 'regression' に設定して、分類または回帰のどちらが必要であるかを指定します。

各アルゴリズムの説明については、「集団アルゴリズム」を参照してください。

適切な集団アルゴリズムの選択に関するヒント」を参照してください。

次の表は、各アルゴリズムの特徴の一覧です。この表では、以下のように表記されています。

  • Regress. — 回帰

  • Classif. — 分類

  • Preds. — 予測子

  • Imbalance — 不均衡なデータ (1 つのクラスに他のクラスよりはるかに多い観測がある) の場合に適切

  • Stop — アルゴリズムが自動終了する

  • Sparse — 必要な弱学習器が他の集団アルゴリズムより少ない

アルゴリズムRegress.Binary Classif.Binary Classif.Multi- Level Preds.Classif.3+ Classesクラスの不均衡停止Sparse
Bag×× ×   
AdaBoostM1 ×     
AdaBoostM2   ×   
LogitBoost ××    
GentleBoost ××    
RobustBoost ×     
LPBoost × × ××
TotalBoost × × ××
RUSBoost × ××  
LSBoost×      
Subspace × ×   

RobustBoostLPBoostTotalBoost には Optimization Toolbox ライセンスが必要です。LPBoost の前に TotalBoost を使用してみてください。TotalBoost の方がロバストな場合があります。

適切な集団アルゴリズムの選択に関するヒント-  

  • 回帰LSBoost または Bag を選択します。ブースティングとバギングの主な違いについては、「集団アルゴリズムの一般的な特徴」を参照してください。

  • 二項分類 — まず AdaBoostM1 を選択し、次のように変更します。

    データの特徴推奨アルゴリズム
    予測子が多数あるSubspace
    データが歪んでいる (1 つのクラスだけに観測が多数ある)RUSBoost
    カテゴリカル予測子のレベル数が 31 を超えているLogitBoost または GentleBoost
    ラベル ノイズ (一部の学習データのクラスが誤っている)RobustBoost
    観測が多数あるLPBoostTotalBoostBag は使用しない

  • マルチクラス分類 — まず AdaBoostM2 を選択し、次のように変更します。

    データの特徴推奨アルゴリズム
    予測子が多数あるSubspace
    データが歪んでいる (1 つのクラスだけに観測が多数ある)RUSBoost
    観測が多数あるLPBoostTotalBoostBag は使用しない

これらのアルゴリズムの詳細は、「集団アルゴリズム」を参照してください。

集団アルゴリズムの一般的な特徴-  

  • Bag では一般的に深いツリーが作成されます。この作成処理は時間がかかり、メモリの消費量も非常に多くなります。このため、予測は比較的低速になります。

  • Boost アルゴリズムでは一般的に非常に浅いツリーが使用されます。この作成処理にかかる時間は比較的短く、メモリの消費量も少なくなります。ただし、効果的な予測を行うには、ブースティング ツリーで必要な集団メンバーの数がバギング ツリーの場合より多くなることがあります。そのため、どちらのアルゴリズムが優れているかは一概には言えません。

  • Bag では、追加の交差検定を行わずに一般化誤差を推定できます。oobLossを参照してください。

  • Subspace を除くすべてのブースティングおよびバギング アルゴリズムはツリー学習器に基づいています。Subspace では判別分析または k 最近傍点学習器を使用できます。

各集団メンバーの特徴の詳細は、「アルゴリズムの特性」を参照してください。

集団メンバー数の設定

速度と精度のバランスが適切に保たれる集団のサイズを選択します。

  • 集団のサイズが大きいと、学習や予測の生成に時間がかかります。

  • アルゴリズムのタイプによっては、サイズが大きすぎると、過学習になる (精度が低下する) 可能性があります。

適切なサイズを設定するには、集団のメンバー数を数十から数百程度から開始して、集団を学習させ、その後で「例:集団の特性テスト」で説明している方法で集団の特性をチェックします。メンバー数を増やす必要があると判断できる場合は、コマンド ラインで resume メソッド (分類木の場合)、または resume メソッド (回帰木の場合) を使用します。メンバーを追加しても集団の特性が改善されなくなるまで手順を繰り返します。

    ヒント:   分類上、LPBoostTotalBoost アルゴリズムは自動終了型です。そのため、適切な集団サイズを調べる必要はありません。numberens500 に設定してみてください。アルゴリズムは通常、これより少ないメンバーで終了します。

弱学習器の準備

現在、弱学習器タイプには次のものがあります。

  • 'Discriminant' (Subspace 集団用)

  • 'KNN' (Subspace 集団用)

  • 'Tree' (Subspace を除くすべての集団用)

集団で弱学習器のタイプを設定するには、2 つの方法があります。

  • 既定の弱学習器オプションで集団を作成するには、弱学習器として文字列を渡します。次に例を示します。

    ens = fitensemble(X,Y,'AdaBoostM2',50,'Tree');
    % or
    ens = fitensemble(X,Y,'Subspace',50,'KNN');
  • 既定の設定でない弱学習器オプションで集団を作成するには、適切な template メソッドを使用して既定の設定でない弱学習器を作成します。たとえば、欠損データがあり、サロゲート分離を含むツリーを使用する場合は次のようにします。

    templ = ClassificationTree.template('Surrogate','all');
    ens = fitensemble(X,Y,'AdaBoostM2',50,templ);

    ツリーごとに約 10 の葉ノードをもつツリーを大きくするには、次のようにします。

    templ = ClassificationTree.template('MinLeaf',size(X,1)/10);
    ens = fitensemble(X,Y,'AdaBoostM2',50,templ);

学習器のテンプレートのセル配列に fitensemble を指定するときに、最もよく使用されるのは、弱学習器を 1 つだけ指定する方法です。

テンプレートの使用例は、「例:不等価な分類コスト」と「サロゲート分割」を参照してください。

決定木では、XNaN 値を処理できます。そのような値は、"欠損している" と呼ばれます。X の行に欠損値が存在する場合は、決定木は欠損していない値のみを使用して最適分割を求めます。行全体が NaN で構成されている場合には、fitensemble はその行を無視します。X のデータに含まれる欠損値の割合が高い場合は、サロゲート決定分割を使用します。サロゲート分割の例は、「例:不等価な分類コスト」と「サロゲート分割」を参照してください。

ツリー弱学習器の一般的な設定-  

  • 弱学習器のツリーの深さによって、学習時間、メモリ使用量および予測精度が変化します。深さは次の 2 つのパラメーターで制御します。

    • MinLeaf — 各リーフには少なくとも MinLeaf の観測値があります。深いツリーを作成するには、MinLeaf に小さい値を指定します。

    • MinParent — ツリーの各分岐ノードには少なくとも MinParent の観測値があります。深いツリーを作成するには、MinParent に小さい値を指定します。

    MinParentMinLeaf 両方を指定する場合は、学習器ではリーフ数が多くなる方の設定を使用します。

    MinParent = max(MinParent,2*MinLeaf)

  • SurrogateSurrogate'on' のときに、サロゲート分割をもつ決定木を成長させます。サロゲート分割はデータに欠損値があるときに使用します。

      メモ:   サロゲート分割を使用すれば学習速度が低下し、メモリ使用量が増えます。

fitensemble の呼び出し

fitensemble の構文は、次のようになります。

ens = fitensemble(X,Y,model,numberens,learners)
  • X は、データの行列です。各行には 1 つの観測値、各列には 1 つの予測子変数が含まれます。

  • Y は応答で、X の行で表される観測値の数と同じ数になります。

  • model は集団のタイプを表す名前の文字列です。

  • numberens は、learners の各要素にある ens の弱学習器の数です。そのため、ens の要素数は、learners の要素数を numberens 倍した数になります。

  • learners は、弱学習器の名前を表す文字列であり、弱学習器のテンプレート、またはそのような文字列やテンプレートのセル配列です。

fitensemble の結果は、新しいデータに対する予測の作成に適した集団オブジェクトです。分類集団の作成に関する基本的な例は、「分類集団の作成」を参照してください。回帰集団の作成に関する基本的な例は、「回帰集団の作成」を参照してください。

名前と値のペアを設定する状況-  関数 fitensemble に渡したり、弱学習器 (ClassificationDiscriminant.templateClassificationKNN.templateClassificationTree.template および RegressionTree.template) に適用できる名前と値のペアがあります。集団または弱学習器では、適切なオプション (名前と値のペア) を判断するために、次のように使用されます。

  • テンプレートの名前と値のペアを使用して、弱学習器の特性を制御します。

  • fitensemble の名前と値のペアを使用して、アルゴリズムまたは構造体のいずれに対しても、集団を全体として制御します。

たとえば、ブースティングされた分類木の集団の各ツリーを既定より深くするには、ClassificationTree.template 名前と値のペア (MinLeafMinParent) を既定の設定よりも小さな値に設定します。これにより、ツリーのリーフ数が増加し、ツリーは深くなります。

集団の予測子の名前を指定するには (集団の構造体の一部にするには)、fitensemblePredictorNames 名前と値のペアを使用します。

基本的な集団の例

分類集団の作成

フィッシャーのアヤメのデータの分類木集団を作成して、平均測定値で花の分類を予測するのに使用します。

  1. データを読み込みます。

    load fisheriris
  2. 予測データ X は行列 meas です。

  3. 応答データ Y はセル配列 species です。

  4. 3 個以上のクラスがある分類木の場合、「適切な集団アルゴリズムの選択に関するヒント」では 'AdaBoostM2' 集団の使用が推奨されています。

  5. この例では、100 本のツリーを指定するものとします。

  6. 既定のツリー テンプレートを使用します。

  7. 集団を作成します。

    ens = fitensemble(meas,species,'AdaBoostM2',100,'Tree')
    ens = 
    
      classreg.learning.classif.ClassificationEnsemble
              PredictorNames: {'x1'  'x2'  'x3'  'x4'}
                ResponseName: 'Y'
                  ClassNames: {'setosa'  'versicolor'  'virginica'}
              ScoreTransform: 'none'
               NObservations: 150
                    NTrained: 100
                      Method: 'AdaBoostM2'
                LearnerNames: {'Tree'}
        ReasonForTermination: [1x77 char]
                     FitInfo: [100x1 double]
          FitInfoDescription: {2x1 cell}
    
    
      Properties, Methods
  8. 平均測定値の花の分類を予測します。

    flower = predict(ens,mean(meas))
    flower = 
    
        'versicolor'

回帰集団の作成

馬力と重量に基づいて自動車の燃費を予測するための回帰集団を作成し、carsmall データで学習させます。作成された集団を使用して、150 馬力、重量 2750 lbs の自動車の燃費を予測します。

  1. データを読み込みます。

    load carsmall
  2. 入力データを準備します。

    X = [Horsepower Weight];
  3. 応答データ YMPG です。

  4. ただ 1 つのブースティングされた回帰集団のタイプは 'LSBoost' です。

  5. この例では、100 本のツリーを指定するものとします。

  6. 既定のツリー テンプレートを使用します。

  7. 集団を作成します。

    ens = fitensemble(X,MPG,'LSBoost',100,'Tree')
    ens = 
    
      classreg.learning.regr.RegressionEnsemble
              PredictorNames: {'x1'  'x2'}
                ResponseName: 'Y'
           ResponseTransform: 'none'
               NObservations: 94
                    NTrained: 100
                      Method: 'LSBoost'
                LearnerNames: {'Tree'}
        ReasonForTermination: [1x77 char]
                     FitInfo: [100x1 double]
          FitInfoDescription: {2x1 cell}
              Regularization: []
    
    
      Properties, Methods
  8. 150 馬力、重量 2750 lbs の自動車の燃費を予測します。

    mileage = ens.predict([150 2750])
    
    mileage =
    
       22.4180

集団の特性テスト

通常、集団の予測特性を学習データでの性能に基づいて評価することはできません。集団は“過学習”になる傾向があり、予測性能について過度に楽観的な予測が行われます。つまり、通常は分類の resubLoss (回帰では resubLoss) の結果は、新しいデータで予測する場合より小さい誤差を示すことを意味します。

集団の特性をより正確に把握できるようにするには、次のいずれかの方式を使用します。

  • 独立したテスト セットで集団を評価します (十分な学習データがあるときに適しています)。

  • 交差検定によって集団を評価します (十分な学習データがないときに適しています)。

  • out-of-bag データで集団を評価します (fitensemble でバギングされた集団を作成するときに適しています)。

例:集団の特性テスト

この例では、集団の特性を評価する 3 つの方式をすべて使用できるように、バギングされた集団を使用します。

  1. 20 の予測子を指定して疑似データセットを生成します。各エントリは 0 ~ 1 のランダムな数です。最初の分類は次のようになります。

    Y = 1 (X(1) + X(2) + X(3) + X(4) + X(5) > 2.5 の場合)
    Y = 0 (上記以外の場合)

    rng(1,'twister') % for reproducibility
    X = rand(2000,20);
    Y = sum(X(:,1:5),2) > 2.5;

    さらに、結果にノイズを追加するために、分類の 10% をランダムに入れ替えます。

    idx = randsample(2000,200);
    Y(idx) = ~Y(idx);
  2. 独立したテスト セット

    独立した学習セットとテスト セットのデータを作成します。cvpartitionholdout オプションを指定して呼び出すことによって、データの 70% を学習セットに使用します。

    cvpart = cvpartition(Y,'holdout',0.3);
    Xtrain = X(training(cvpart),:);
    Ytrain = Y(training(cvpart),:);
    Xtest = X(test(cvpart),:);
    Ytest = Y(test(cvpart),:);
  3. 学習データを基にツリー数 200 のバギングされた分類集団を作成します。

    bag = fitensemble(Xtrain,Ytrain,'Bag',200,'Tree',...
        'type','classification')
    bag = 
    
      classreg.learning.classif.ClassificationBaggedEnsemble
              PredictorNames: {1x20 cell}
                ResponseName: 'Y'
                  ClassNames: [0 1]
              ScoreTransform: 'none'
               NObservations: 1400
                    NTrained: 200
                      Method: 'Bag'
                LearnerNames: {'Tree'}
        ReasonForTermination: [1x77 char]
                     FitInfo: []
          FitInfoDescription: 'None'
                   FResample: 1
                     Replace: 1
            UseObsForLearner: [1400x200 logical]
    
    
      Properties, Methods
  4. 検定データの損失 (誤判別) を集団内の学習済みのツリー数の関数としてプロットします。

    figure;
    plot(loss(bag,Xtest,Ytest,'mode','cumulative'));
    xlabel('Number of trees');
    ylabel('Test classification error');

  5. 交差検定

    5 分割交差検定を使用したバギングされた集団を生成します。

    cv = fitensemble(X,Y,'Bag',200,'Tree',...
        'type','classification','kfold',5)
    cv = 
    
      classreg.learning.partition.ClassificationPartitionedEnsemble
          CrossValidatedModel: 'Bag'
               PredictorNames: {1x20 cell}
        CategoricalPredictors: []
                 ResponseName: 'Y'
                NObservations: 2000
                        KFold: 5
                    Partition: [1x1 cvpartition]
              NTrainedPerFold: [200 200 200 200 200]
                   ClassNames: [0 1]
               ScoreTransform: 'none'
    
    
      Properties, Methods
  6. 交差検定損失を集団内のツリー数の関数として検査します。

    figure;
    plot(loss(bag,Xtest,Ytest,'mode','cumulative'));
    hold on;
    plot(kfoldLoss(cv,'mode','cumulative'),'r.');
    hold off;
    xlabel('Number of trees');
    ylabel('Classification error');
    legend('Test','Cross-validation','Location','NE');

    交差検定では、独立したセットに見合った推定が生成されています。

  7. out-of-bag 推定

    out-of-bag 推定の損失曲線を生成し、他の曲線と共にプロットします。

    figure;
    plot(loss(bag,Xtest,Ytest,'mode','cumulative'));
    hold on;
    plot(kfoldLoss(cv,'mode','cumulative'),'r.');
    plot(oobLoss(bag,'mode','cumulative'),'k--');
    hold off;
    xlabel('Number of trees');
    ylabel('Classification error');
    legend('Test','Cross-validation','Out of bag','Location','NE');

    out-of-bag 推定でも、他の手法と同等の結果が示されています。

不均衡データでの分類

この例では、1 つのクラスに他のクラスより多くの観測値が含まれる場合の分類方法を示します。このような場合に対応する RUSBoost アルゴリズムを試してみましょう。

この例では、UCI 機械学習アーカイブの "Cover type" データ (詳細は「http://archive.ics.uci.edu/ml/datasets/Covertype」を参照) を使用します。このデータでは、森林被覆の種類を、標高、土壌の種類、水源までの距離などの予測子に基づいて分類しています。このデータには 500,000 件を超える観測と 50 を超える予測子があるため、トレーニングや分類器の使用には時間がかかる場合があります。

Blackard と Dean [1] がこのデータのニューラル ネット分類について説明しています。それによると、分類の精度は 70.6% になっています。RUSBoost の分類の精度は 76% を超えます (手順 6 および 7 を参照してください)。

手順 1. データを取得する。

urlwrite('http://archive.ics.uci.edu/ml/machine-learning-databases/covtype/covtype.data.gz','forestcover.gz');

次に、forestcover.gz ファイルからデータを抽出します。データは covtype.data ファイルにあります。

手順 2. データをインポートして分類の準備をする。

データをワークスペースにインポートします。最後のデータ列を抽出して Y という名前の変数に格納します。

load covtype.data
Y = covtype(:,end);
covtype(:,end) = [];

手順 3. 応答データを調べる。

tabulate(Y)
  Value    Count   Percent
      1    211840     36.46%
      2    283301     48.76%
      3    35754      6.15%
      4     2747      0.47%
      5     9493      1.63%
      6    17367      2.99%
      7    20510      3.53%

データ ポイントは何十万個もあります。クラス 4 のデータ ポイントは全体の 0.5% 未満です。このような不均衡なデータには、RUSBoost アルゴリズムが適切です。

手順 4. データを分割して品質評価する。

データの半分は分類器の近似に使用し、残りの半分は生成された分類器の品質評価に使用します。

part = cvpartition(Y,'holdout',0.5);
istrain = training(part); % data for fitting
istest = test(part); % data for quality assessment
tabulate(Y(istrain))
  Value    Count   Percent
      1    105920     36.46%
      2    141651     48.76%
      3    17877      6.15%
      4     1374      0.47%
      5     4746      1.63%
      6     8683      2.99%
      7    10255      3.53%

手順 5. 集団を作成する。

深いツリーを使用して集団の精度を上げます。そのためには、ツリーの最小の葉のサイズを 5 に設定します。また、LearnRate0.1 に設定し、精度が高くなるようにします。データは大規模で、深いツリーがあると集団の作成に時間がかかります。

t = ClassificationTree.template('minleaf',5);
tic
rusTree = fitensemble(covtype(istrain,:),Y(istrain),'RUSBoost',1000,t,...
    'LearnRate',0.1,'nprint',100);
toc
Training RUSBoost...
Grown weak learners: 100
Grown weak learners: 200
Grown weak learners: 300
Grown weak learners: 400
Grown weak learners: 500
Grown weak learners: 600
Grown weak learners: 700
Grown weak learners: 800
Grown weak learners: 900
Grown weak learners: 1000
Elapsed time is 918.258401 seconds.

手順 6. 分類エラーを検証する。

集団のメンバー数に対して分類エラーをプロットします。

figure;
tic
plot(loss(rusTree,covtype(istest,:),Y(istest),'mode','cumulative'));
toc
grid on;
xlabel('Number of trees');
ylabel('Test classification error');
Elapsed time is 775.646935 seconds.

この集団は、使用しているツリー数が 150 以上の場合に、分類エラーが 24% 未満となっています。ツリーの数が 400 以上になると、エラーが最低水準となります。

各クラスの混合行列を、真のクラスのパーセンテージとして調べます。

tic
Yfit = predict(rusTree,covtype(istest,:));
toc
tab = tabulate(Y(istest));
bsxfun(@rdivide,confusionmat(Y(istest),Yfit),tab(:,2))*100
Elapsed time is 427.293168 seconds.

ans =

  Columns 1 through 6

   83.3771    7.4056    0.0736         0    1.7051    0.2681
   18.3156   66.4652    2.1193    0.0162    9.3435    2.8239
         0    0.0839   90.8038    2.3885    0.6545    6.0693
         0         0    2.4763   95.8485         0    1.6752
         0    0.2739    0.6530         0   98.6518    0.4213
         0    0.1036    3.8346    1.1400    0.4030   94.5187
    0.2340         0         0         0    0.0195         0

  Column 7

    7.1705
    0.9163
         0
         0
         0
         0
   99.7465

クラス 2 を除くすべてのクラスで分類の精度が 80% を超え、クラス 3 ~ 7 では精度が 90% を超えています。ただし、クラス 2 はデータの約半分を占めているため、全体の精度はそれほど高くなりません。

手順 7. 集団を圧縮します。

集団は大きくなっています。メソッド compact を使ってデータを除去します。

cmpctRus = compact(rusTree);

sz(1) = whos('rusTree');
sz(2) = whos('cmpctRus');
[sz(1).bytes sz(2).bytes]
ans =

   1.0e+09 *

    1.6947    0.9790

圧縮された集団のサイズは、元の集団の約半分です。

ツリーの半分を cmpctRus から削除します。この操作による予測性能への影響は最小限に抑えられます。これは、1000 個のツリーのうち 400 個を使用すれば最適な精度が得られるという観測に基づいています。

cmpctRus = removeLearners(cmpctRus,[500:1000]);

sz(3) = whos('cmpctRus');
sz(3).bytes
ans =

   475495669

圧縮された集団で消費されるメモリは、完全な状態の集団の場合と比べて約 4 分の 1 になります。全体での損失の割合は 24% 未満となります。

L = loss(cmpctRus,covtype(istest,:),Y(istest))
L =

    0.2326

集団の精度にバイアスがある可能性があるため、新しいデータについての予測精度は異なる場合があります。このバイアスが発生するのは、集団サイズの圧縮に集団の評価と同じデータが使用されるためです。必要な集団サイズについて不偏推定値を得るには、交差検定を実行します。ただし、この処理は時間がかかります。

分類の場合:不均衡なデータまたは不等価な誤判別のコスト

実世界で応用する場合には、データのクラスを非対称的に処理したい場合があります。たとえば、データに他のクラスより多くの観測値をもつクラスがあるとします。または、取り組んでいる問題で、他のクラスで発生した場合より深刻な結果をもたらす誤判別が、1 つのクラスで発生するとします。そのような状況では、関数 fitensemblepriorcost の 2 つのオプション パラメーターが使用できます。

prior を使用することによって、優先クラス確率 (つまり、学習に使用されるクラスの確率) を設定します。学習セットに過小または過大に表現されるクラスがある場合に、このオプションを使用します。たとえば、シミュレーションによって学習データを取得するとします。シミュレートするクラス A は、クラス B よりも計算の負荷が高いため、クラス A の観測値は少なめに、また B の観測値は多めに生成される傾向になります。しかし、実世界ではクラス A とクラス B がそれとは異なる比率で混在していると考えられます。このケースでは、実世界で観測される値に近い比率になるように、クラス AB に事前確率を設定します。fitensemble は事前確率を正規化して、合計 1 になるようにします。すべての事前確率に同じ正因子を乗算しても、分類の結果には影響しません。

学習データでクラスが適切に表現されていても、それらを非対称的に処理したい場合には、cost パラメーターを使用します。癌患者の良性腫瘍と悪性腫瘍を分類したいとします。悪性腫瘍の特定に失敗すること (偽陰性) は、良性を悪性と誤診する (偽陽性) よりも深刻な結果をもたらします。悪性を良性と誤診する場合には高いコストを、良性を悪性と誤診する場合には低いコストを割り当てなければならないはずです。

誤判別のコストは、非負の要素をもつ正方行列として渡さなければなりません。この行列の要素 C(i,j) は、真のクラスが i である場合に、観測値をクラス j に分類するコストを表します。コスト行列 C(i,i) の対角要素は、0 でなければなりません。前の例では、悪性腫瘍をクラス 1、良性腫瘍をクラス 2 として選択できます。次に、コスト行列を次のように設定します。

ここで、c > 1 は、悪性腫瘍を良性と誤診した場合のコストを表します。コストは相対値です。すべてのコストに同じ正因子を乗算しても、分類の結果に影響はありません。

クラスが 2 つしかない場合は、fitensemble はクラス i = 1,2 と j ≠ i に対して、 を使用して、事前確率を調整します。Pi は事前確率であり、fitensemble に渡されるか、学習データでのクラスの頻度から計算されます。また、 は、調整済みの事前確率です。次に、fitensemble は既定のコスト行列を使用します。

さらに、これらの調整済みの確率を弱学習器の学習に使用します。つまり、コスト行列の操作は事前確率の操作と等価です。

3 つ以上のクラスを使用する場合も、fitensemble は入力コストを調整済み事前確率に変換します。この変換はさらに複雑です。まず、fitensemble は、Zhou と Liu の[20]で説明されている行列方程式を解こうとします。解を求めるのに失敗した場合は、fitensemble は Breiman などによって説明されている "平均コスト" を適用します。 「[6]」。詳細は、Zadrozny、Langford および Abe [19] を参照してください。

例:不等価な分類コスト

この例では、肝炎患者に関するデータを使用して、疾病によって生存するか、または死亡するかを確認します。データは http://archive.ics.uci.edu/ml/datasets/Hepatitis で説明されています。

  1. データを hepatitis.txt という名前のファイルに読み込みます。

    s = urlread(['http://archive.ics.uci.edu/ml/' ...
      'machine-learning-databases/hepatitis/hepatitis.data']);
    fid = fopen('hepatitis.txt','w');
    fwrite(fid,s);
    fclose(fid);
  2. データ hepatitis.txt をデータセットに読み込みます。データのフィールドを記述する変数名は次のようにします。

    VarNames = {'die_or_live' 'age' 'sex' 'steroid' 'antivirals' 'fatigue' ...
        'malaise' 'anorexia' 'liver_big' 'liver_firm' 'spleen_palpable' ...
        'spiders' 'ascites' 'varices' 'bilirubin' 'alk_phosphate' 'sgot' ...
        'albumin' 'protime' 'histology'};
    ds = dataset('file','hepatitis.txt','VarNames',VarNames,...
        'Delimiter',',','ReadVarNames',false,'TreatAsEmpty','?',...
        'Format','%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f');

    ds は、155 の観測値と 20 の変数をもつデータセットです。

    size(ds)
    ans =
    
       155    20
  3. データセットのデータを集団の形式に変換します。つまり、予測子の数値行列と'Die' または 'Live' の出力名をもつセル配列に変換します。データセットの最初のフィールドに結果が格納されます。

    X = double(ds(:,2:end));
    ClassNames = {'Die' 'Live'};
    Y = ClassNames(ds.die_or_live);
  4. 欠損値についてデータを検査します。

    figure;
    bar(sum(isnan(X),1)/size(X,1));
    xlabel('Predictor');
    ylabel('Fraction of missing values');

    ほとんどの予測子に欠損値があり、その 1 つでは 45% 近くが欠損値となっています。そのため、サロゲート分割をもつ決定木を使用することによって精度を高めます。データセットのサイズが小さいため、サロゲート分割を使用した場合でも学習時間はそれほど長くはなりません。

  5. サロゲート分割を使用する分類木のテンプレートを作成します。

    rng(0,'twister') % for reproducibility
    t = ClassificationTree.template('surrogate','all');
  6. データまたはデータの説明を検証して、カテゴリカル予測子を特定します。

    X(1:5,:)
    ans =
    
      Columns 1 through 6
    
       30.0000    2.0000    1.0000    2.0000    2.0000    2.0000
       50.0000    1.0000    1.0000    2.0000    1.0000    2.0000
       78.0000    1.0000    2.0000    2.0000    1.0000    2.0000
       31.0000    1.0000       NaN    1.0000    2.0000    2.0000
       34.0000    1.0000    2.0000    2.0000    2.0000    2.0000
    
      Columns 7 through 12
    
        2.0000    1.0000    2.0000    2.0000    2.0000    2.0000
        2.0000    1.0000    2.0000    2.0000    2.0000    2.0000
        2.0000    2.0000    2.0000    2.0000    2.0000    2.0000
        2.0000    2.0000    2.0000    2.0000    2.0000    2.0000
        2.0000    2.0000    2.0000    2.0000    2.0000    2.0000
    
      Columns 13 through 18
    
        2.0000    1.0000   85.0000   18.0000    4.0000       NaN
        2.0000    0.9000  135.0000   42.0000    3.5000       NaN
        2.0000    0.7000   96.0000   32.0000    4.0000       NaN
        2.0000    0.7000   46.0000   52.0000    4.0000   80.0000
        2.0000    1.0000       NaN  200.0000    4.0000       NaN
    
      Column 19
    
        1.0000
        1.0000
        1.0000
        1.0000
        1.0000

    予測子 213、および予測子 19 はカテゴリカルであると判断されます。この推論は、http://archive.ics.uci.edu/ml/datasets/Hepatitis のデータセットの説明によって確認できます。

  7. カテゴリカル変数をリストします。

    ncat = [2:13,19];
  8. 150 の学習器と GentleBoost アルゴリズムを使用して、交差検定を使用した集団を作成します。

    a = fitensemble(X,Y,'GentleBoost',150,t,...
      'PredictorNames',VarNames(2:end),'LearnRate',0.1,...
      'CategoricalPredictors',ncat,'kfold',5);
    figure;
    plot(kfoldLoss(a,'mode','cumulative','lossfun','exponential'));
    xlabel('Number of trees');
    ylabel('Cross-validated exponential loss');

  9. 混合行列を検査して、集団によって正しく予測された人々を確認します。

    [Yfit,Sfit] = kfoldPredict(a); % 
    confusionmat(Y,Yfit,'order',ClassNames)
    ans =
    
        18    14
        11   112

    生存した 123 名については、112 名の生存が正しく予測されています。しかし、肝炎で死亡した 32 名については、実際に肝炎で死亡した患者の約半数が正しく予測されただけです。

  10. 集団による予測で発生する誤差には、次の 2 つのタイプがあります。

    • 患者の生存を予測したにも関わらず、患者が死亡した場合

    • 患者の死亡を予測したにも関わらず、患者が生存した場合

    1 番目の誤差は 2 番目の誤差より 5 倍の悪影響をもたらすという前提があるとします。この前提を反映した新しい分類コスト行列を作成します。

    cost.ClassNames = ClassNames;
    cost.ClassificationCosts = [0 5; 1 0];
  11. 誤判別のコストに cost を使用する新しい交差検定集団を作成して、結果の混合行列を検査します。

    aC = fitensemble(X,Y,'GentleBoost',150,t,...
      'PredictorNames',VarNames(2:end),'LearnRate',0.1,...
      'CategoricalPredictors',ncat,'kfold',5,...
      'cost',cost);
    [YfitC,SfitC] = kfoldPredict(aC);
    confusionmat(Y,YfitC,'order',ClassNames)
    ans =
    
        19    13
         8   115

    予想どおり、新しい集団では死亡する患者の分類機能が向上しています。意外なことに、新しい集団では、統計的には飛躍的な改善ではないものの、生存する患者の分類においても向上が見られます。交差検定の結果は無作為であるため、この結果は単なる統計変動です。結果によれば、生存する患者の分類については、コストに大きな影響は与えないことが示されていると判断されます。

カテゴリカル レベルの数が多い分類

一般に、カテゴリカル予測子では、31 を超えるレベルの分類は使用できません。ただし、2 つのブースティング アルゴリズムを使用すれば、カテゴリカル予測子レベルやバイナリ応答の多いデータを分類できます。これらは LogitBoostGentleBoost の 2 つです。詳細は、LogitBoostGentleBoost を参照してください。

この例では、http://archive.ics.uci.edu/ml/machine-learning-databases/adult/ で公開されている、米国の国勢調査から人口統計学データを使用します。データを掲載した研究者の目的は、各種の特性に基づいて、ある人が年間 5000 ドル以上の収入を得ることが可能かどうかを予測することにあります。予測子の名前など、データの詳細については、サイトにある adult.names ファイルで確認できます。

  1. UCI 機械学習リポジトリから 'adult.data' ファイルを読み込みます。

    s = urlread(['http://archive.ics.uci.edu/ml/' ...
       'machine-learning-databases/adult/adult.data']);
  2. 'adult.data' では、欠損データは '?' で表されています。欠損データのインスタンスを空白文字列 '' で置き換えます。

    s = strrep(s,'?','');
  3. データを MATLAB® のデータセット配列に読み込みます。

    fid = fopen('adult.txt','w');
    fwrite(fid,s);
    fclose(fid);
    clear s;
    VarNames = {'age' 'workclass' 'fnlwgt' 'education' 'education_num' ...
        'marital_status' 'occupation' 'relationship' 'race' ...
        'sex' 'capital_gain' 'capital_loss' ...
        'hours_per_week' 'native_country' 'income'};
    ds = dataset('file','adult.txt','VarNames',VarNames,...
        'Delimiter',',','ReadVarNames',false,'Format',...
       '%u%s%u%s%u%s%s%s%s%s%u%u%u%s%s');
    cat = ~datasetfun(@isnumeric,ds(:,1:end-1)); % Logical indices
    %                                             of categorical variables
    catcol = find(cat); % indices of categorical variables

  4. データ内の多くの予測子はカテゴリカルです。データセット配列のそれらのフィールドを nominal に変換します。

    ds.workclass = nominal(ds.workclass);
    ds.education = nominal(ds.education);
    ds.marital_status = nominal(ds.marital_status);
    ds.occupation = nominal(ds.occupation);
    ds.relationship = nominal(ds.relationship);
    ds.race = nominal(ds.race);
    ds.sex = nominal(ds.sex);
    ds.native_country = nominal(ds.native_country);
    ds.income = nominal(ds.income);
  5. データセット配列を fitensemble の数値変数に変換します。

    X = double(ds(:,1:end-1));
    Y = ds.income;
  6. 一部の変数には複数のレベルがあります。各予測子のレベルの数をプロットします。

    ncat = zeros(1,numel(catcol));
    for c=1:numel(catcol)
        [~,gn] = grp2idx(X(:,catcol(c)));
        ncat(c) = numel(gn);
    end
    figure;
    bar(catcol,ncat);
    xlabel('Predictor');
    ylabel('Number of categories');

    予測子 14 ('native_country') には、40 を超えるカテゴリカル レベルがあります。二項分類の場合、ClassificationTree.fit では、計算のショートカットを使用して、多くのカテゴリを含むカテゴリカル予測子の最適な分割を見つけます。3 つ以上のクラスを含む分類の場合は、経験則アルゴリズムを選択して最適な分割を見つけることができます。カテゴリカル予測子の分割 を参照してください。

  7. LogitBoost および GentleBoost を使用して、分類集団を作成します。

    lb = fitensemble(X,Y,'LogitBoost',300,'Tree','CategoricalPredictors',cat,...
        'PredictorNames',VarNames(1:end-1),'ResponseName','income');
    gb = fitensemble(X,Y,'GentleBoost',300,'Tree','CategoricalPredictors',cat,...
        'PredictorNames',VarNames(1:end-1),'ResponseName','income');

  8. 2 つの集団の再置換誤差を検査します。

    figure;
    plot(resubLoss(lb,'mode','cumulative'));
    hold on
    plot(resubLoss(gb,'mode','cumulative'),'r--');
    hold off
    xlabel('Number of trees');
    ylabel('Resubstitution error');
    legend('LogitBoost','GentleBoost','Location','NE');

    GentleBoost アルゴリズムの再置換誤差はやや少なめです。

  9. 交差検定によって、2 つのアルゴリズムの一般化誤差を推定します。

    lbcv = crossval(lb,'kfold',5);
    gbcv = crossval(gb,'kfold',5);
    figure;
    plot(kfoldLoss(lbcv,'mode','cumulative'));
    hold on
    plot(kfoldLoss(gbcv,'mode','cumulative'),'r--');
    hold off
    xlabel('Number of trees');
    ylabel('Cross-validated error');
    legend('LogitBoost','GentleBoost','Location','NE');

    交差検定損失は、再置換誤差とほとんど同じです。

サロゲート分割

欠損データがある場合は、サロゲート分割を使用すれば、ツリーとツリーの集団の予測性能が向上します。さらに、サロゲート分割を使用することによって、多くの場合、予測子の重要度に関する推測結果も変化します。重要度の低い予測子を推測することによって、予測に必要な時間やメモリを節約できるだけでなく、予測の動作についても理解しやすくなります。

この例では、テスト セットに欠損値が含まれるデータの予測に、サロゲート分割を使用した場合の影響を示します。

  1. 標本データを読み込みます。そのデータを学習セットおよびテスト セットに分割します。

    load ionosphere;
    
    rng(10) % for reproducibility
    cv = cvpartition(Y,'holdout',0.3);
    Xtrain = X(training(cv),:);
    Ytrain = Y(training(cv));
    Xtest = X(test(cv),:);
    Ytest = Y(test(cv));
  2. サロゲート分割を使用してまたは使用せずに決定木をバギングします。

    b = fitensemble(Xtrain,Ytrain,'Bag',50,'Tree',...
         'type','class');
    
    templS = ClassificationTree.template('surrogate','on');
    bs = fitensemble(Xtrain,Ytrain,'Bag',50,templS,...
        'type','class');
    
  3. テスト セットの値の半分が欠損しているものとします。

    Xtest(rand(size(Xtest))>0.5) = NaN;
  4. サロゲート分割を使用してまたは使用せずに精度を検定します。

    figure;
    plot(loss(b,Xtest,Ytest,'mode','cumulative'));
    hold on;
    plot(loss(bs,Xtest,Ytest,'mode','cumulative'),'r--');
    legend('Regular trees','Trees with surrogate splits');
    xlabel('Number of trees');
    ylabel('Test classification error');

  5. マクネマー検定を使用して結果に見られる相違の統計的有意性をチェックします。ラベルを nominal データ型に変換して、等価性を簡単にチェックできるようにします。

    Yfit = nominal(predict(b,Xtest));
    YfitS = nominal(predict(bs,Xtest));
    N10 = sum(Yfit==nominal(Ytest) & YfitS~=nominal(Ytest));
    N01 = sum(Yfit~=nominal(Ytest) & YfitS==nominal(Ytest));
    mcnemar = (abs(N10-N01) - 1)^2/(N10+N01);
    pval = 1 - chi2cdf(mcnemar,1)
    pval =
    
       1.7683e-04

    p 値が極端に低いのは、サロゲート分割を使用した集団が統計的有意性から見ても優れた結果を残していることを示しています。

小さい集団での LPBoost と TotalBoost

この例では、LPBoost および TotalBoost アルゴリズムを活用する方法を示します。これらのアルゴリズムは、いずれも次のような利点があります。

自動終了するため、使用するメンバーの数を考慮する必要がない。

重みが非常に小さい集団が生成されるため、集団のメンバーを安全に削除できる。

この例のアルゴリズムは Optimization Toolbox ライセンスが必要であることに注意してください。

手順 1. データを読み込む。

ionosphere データを読み込みます。

load ionosphere

手順 2. 分類集団を作成する。

ionosphere データを分類するための集団を、LPBoostTotalBoost アルゴリズムを使用して作成します。また、比較する場合は AdaBoostM1 アルゴリズムを使用します。集団に使用するメンバーの数を把握するのは困難です。LPBoostTotalBoost で 500 を使用してみます。また、比較のために、AdaBoostM1 でも 500 を使用します。

rng default % for reproducibility
T = 500;
adaStump = fitensemble(X,Y,'AdaBoostM1',T,'Tree');
totalStump = fitensemble(X,Y,'TotalBoost',T,'Tree');
lpStump = fitensemble(X,Y,'LPBoost',T,'Tree');
figure;
plot(resubLoss(adaStump,'mode','cumulative'));
hold on
plot(resubLoss(totalStump,'mode','cumulative'),'r');
plot(resubLoss(lpStump,'mode','cumulative'),'g');
hold off
xlabel('Number of stumps');
ylabel('Training error');
legend('AdaBoost','TotalBoost','LPBoost','Location','NE');

3 つのアルゴリズムはいずれも、後で学習データに関する最適な予測ができるようになっています。3 つの集団すべてのメンバー数を調べます。

[adaStump.NTrained totalStump.NTrained lpStump.NTrained]
ans =

   500    52    67

AdaBoostM1 は 500 件のメンバーすべてをトレーニングしました。他の 2 つのアルゴリズムのトレーニングは早期に停止しています。

手順 3. 集団を交差検定する。

集団を交差検定して、集団の精度をより詳細に把握します。

cvlp = crossval(lpStump,'kfold',5);
cvtotal = crossval(totalStump,'kfold',5);
cvada = crossval(adaStump,'kfold',5);

figure;
plot(kfoldLoss(cvada,'mode','cumulative'));
hold on
plot(kfoldLoss(cvtotal,'mode','cumulative'),'r');
plot(kfoldLoss(cvlp,'mode','cumulative'),'g');
hold off
xlabel('Ensemble size');
ylabel('Cross-validated error');
legend('AdaBoost','TotalBoost','LPBoost','Location','NE');

各ブースティング アルゴリズムでは集団のメンバー数が 50 の場合の損失が 10% 以下で、AdaBoostM1 では集団のメンバー数が 150 以上の場合の誤差が約 6% となります。

手順 4. 集団のメンバーを圧縮および削除する。

集団のサイズを小さくするには、集団を圧縮し、removeLearners メソッドを使用します。ここで問題となるのは「学習器をいくつ削除すればよいか」です。このための測定方法の 1 つとして、交差検定損失曲線があげられます。また、圧縮後に LPBoostTotalBoost の学習器の重みを調べるという方法もあります。

cada = compact(adaStump);
clp = compact(lpStump);
ctotal = compact(totalStump);

figure
subplot(2,1,1)
plot(clp.TrainedWeights)
title('LPBoost weights')
subplot(2,1,2)
plot(ctotal.TrainedWeights)
title('TotalBoost weights')

LPBoostTotalBoost のいずれも、集団のメンバーの重みが無視できるようになるポイントが明確です。

重要でない集団のメンバーを削除します。

cada = removeLearners(cada,150:cada.NTrained);
clp = removeLearners(clp,60:clp.NTrained);
ctotal = removeLearners(ctotal,40:ctotal.NTrained);

これらの学習器を削除しても学習データに対する集団の精度に影響がないことを確認します。

[loss(cada,X,Y) loss(clp,X,Y) loss(ctotal,X,Y)]
ans =

     0     0     0

圧縮後の集団のサイズを確認します。

s(1) = whos('cada');
s(2) = whos('clp');
s(3) = whos('ctotal');
s.bytes
ans =
      605605

ans =
      241375

ans =
      160435

圧縮後の集団のサイズは、各集団のメンバーの数にほぼ比例します。

集団の正則化

正則化とは、予測性能を低下させずに、集団のために選択する弱学習器の数を少なくするプロセスです。現在のところ、正則化できるのは回帰集団です。(非集団のコンテキストで判別分析分類器を正則化することもできます。「判別分析分類器の正則化」を参照してください)。

regularize メソッドは、最小化が可能な学習器の最適な重みのセット αt を求めます。

ここで、

  • λ ≥ 0 は、指定するパラメーターで、lasso パラメーターと呼ばれます。

  • ht は、予測子 xn、応答 yn、および重み wn をもつ N 個の観測値について学習した集団に含まれる弱学習器です。

  • g(f,y) = (f – y)2 は、二乗誤差です。

集団は、学習に使用されたのと同じ (xn,yn,wn) データについて正則化されます。そのため、

は、集団再置換誤差です。この誤差は二乗平均誤差 (MSE) によって測定されます。

λ = 0 を使用した場合、regularize は、再置換 MSE が最小にすることによって、弱学習器の重みを求めます。集団には過学習の傾向があります。つまり、再置換誤差は実際の一般化誤差より通常は少なくなります。再置換誤差をさらに少なくすることによって、集団の精度が向上するどころか、逆に低下する結果になりやすいといえます。反対に、λ を正の値にすることによって、αt 係数の大きさを 0 に近付けます。これは、多くの場合、一般化誤差の改善につながります。もちろん、大きすぎる λ を選択した場合には、すべての最適係数が 0 になり、集団の精度は失われます。通常は、正則化された集団が正則化されないフル セットの集団と同等かそれ以上の精度になるような、λ の最適な範囲を求めることができます。

Lasso 正則化が便利なのは、最適化された係数を正確に 0 にできる機能があるためです。学習器の重み αt が 0 の場合、この学習器を正則化集団から除外することができます。結果的に、精度が高く、学習器の数が少ない集団が得られることになります。

例:回帰集団の正則化

この例では、多くの属性に基づいて、自動車の保険リスクを予測するためのデータを使用します。

  1. imports-85 データを MATLAB ワークスペースに読み込みます。

    load imports-85;
  2. データの説明を参照して、カテゴリカル変数と予測子名を探します。

    Description
    Description =
    1985 Auto Imports Database from the UCI repository                             
    http://archive.ics.uci.edu/ml/machine-learning-databases/autos/imports-85.names
    Variables have been reordered to place variables with numeric values (referred 
    to as "continuous" on the UCI site) to the left and categorical values to the  
    right. Specifically, variables 1:16 are: symboling, normalized-losses,         
    wheel-base, length, width, height, curb-weight, engine-size, bore, stroke,     
    compression-ratio, horsepower, peak-rpm, city-mpg, highway-mpg, and price.     
    Variables 17:26 are: make, fuel-type, aspiration, num-of-doors, body-style,    
    drive-wheels, engine-location, engine-type, num-of-cylinders, and fuel-system.

    このプロセスの目的は、データの最初の変数である “シンボル化” を他の予測子から予測することにあります。“シンボル化” は、-3 (保険リスクが低い) から 3 (保険リスクが高い) までの整数値です。ここで、回帰集団の代わりに分類集団を使用して、このリスクを予測できる場合もあります。「教師あり学習 (機械学習) の手順」で説明されているように、回帰と分類を選択できるケースでは、最初に回帰の使用を試みます。さらに、この例では、現在は回帰でのみ使用できる正則化についても取り上げています。

  3. 集団の近似に使用するデータを準備します。

    Y = X(:,1);
    X(:,1) = [];
    VarNames = {'normalized-losses' 'wheel-base' 'length' 'width' 'height' ...
      'curb-weight' 'engine-size' 'bore' 'stroke' 'compression-ratio' ...
      'horsepower' 'peak-rpm' 'city-mpg' 'highway-mpg' 'price' 'make' ...
      'fuel-type' 'aspiration' 'num-of-doors' 'body-style' 'drive-wheels' ...
      'engine-location' 'engine-type' 'num-of-cylinders' 'fuel-system'};
    catidx = 16:25; % indices of categorical predictors

  4. 300 本の既定のツリーを使用して、データから回帰集団を作成します。

    ls = fitensemble(X,Y,'LSBoost',300,'Tree','LearnRate',0.1,...
        'PredictorNames',VarNames,'ResponseName','symboling',...
        'CategoricalPredictors',catidx)
    ls = 
    
      classreg.learning.regr.RegressionEnsemble
              PredictorNames: {1x25 cell}
                ResponseName: 'symboling'
           ResponseTransform: 'none'
               NObservations: 205
                    NTrained: 300
                      Method: 'LSBoost'
                LearnerNames: {'Tree'}
        ReasonForTermination: [1x77 char]
                     FitInfo: [300x1 double]
          FitInfoDescription: {2x1 cell}
              Regularization: []
    
    
      Properties, Methods

    最後の行、Regularization は空 ([]) です。集団を正則化するには、regularize メソッドを使用しなければなりません。

  5. 集団に交差検定を実施して、損失曲線を検査します。

    cv = crossval(ls,'kfold',5);
    figure;
    plot(kfoldLoss(cv,'mode','cumulative'));
    xlabel('Number of trees');
    ylabel('Cross-validated MSE');
    ylim([0.2,2])

    結果によれば、50 ~ 100 本のツリーで構成されるように、集団のサイズを小さくすることによって、満足な性能が得られると判断できます。

  6. regularize メソッドを呼び出し、集団から削除できるツリーを求めます。既定の設定では、regularize は指数関数的な間隔の lasso (Lambda) パラメーターの 10 個の値を検査します。

    ls = regularize(ls)
    ls = 
    
      classreg.learning.regr.RegressionEnsemble
              PredictorNames: {1x25 cell}
                ResponseName: 'symboling'
           ResponseTransform: 'none'
               NObservations: 205
                    NTrained: 300
                      Method: 'LSBoost'
                LearnerNames: {'Tree'}
        ReasonForTermination: [1x77 char]
                     FitInfo: [300x1 double]
          FitInfoDescription: {2x1 cell}
              Regularization: [1x1 struct]
    
    
      Properties, Methods

    ここでは、Regularization プロパティは空ではありません。

  7. lasso パラメーターに対して、再置換平均二乗誤差 (MSE) と重みがゼロでない学習器の数をプロットします。Lambda=0 での値は別にプロットします。Lambda の値は指数関数的な間隔であるため、対数スケールを使用します。

    figure;
    semilogx(ls.Regularization.Lambda,ls.Regularization.ResubstitutionMSE);
    line([1e-3 1e-3],[ls.Regularization.ResubstitutionMSE(1) ...
         ls.Regularization.ResubstitutionMSE(1)],...
        'marker','x','markersize',12,'color','b');
    r0 = resubLoss(ls);
    line([ls.Regularization.Lambda(2) ls.Regularization.Lambda(end)],...
         [r0 r0],'color','r','LineStyle','--');
    xlabel('Lambda');
    ylabel('Resubstitution MSE');
    annotation('textbox',[0.5 0.22 0.5 0.05],'String','unregularized ensemble',...
        'color','r','FontSize',14,'LineStyle','none');
    
    figure;
    loglog(ls.Regularization.Lambda,sum(ls.Regularization.TrainedWeights>0,1));
    line([1e-3 1e-3],...
        [sum(ls.Regularization.TrainedWeights(:,1)>0) ...
        sum(ls.Regularization.TrainedWeights(:,1)>0)],...
        'marker','x','markersize',12,'color','b');
    line([ls.Regularization.Lambda(2) ls.Regularization.Lambda(end)],...
        [ls.NTrained ls.NTrained],...
        'color','r','LineStyle','--');
    xlabel('Lambda');
    ylabel('Number of learners');
    annotation('textbox',[0.3 0.8 0.5 0.05],'String','unregularized ensemble',...
        'color','r','FontSize',14,'LineStyle','none');

  8. 再置換 MSE の値は過度に楽観的になる傾向があります。Lambda のさまざまな値に関連する誤差について信頼性の高い推定を得るには、cvshrink を使用して交差検定を実施します。Lambda に対して、交差検定損失 (MSE) の結果と学習器の数をプロットします。

    rng(0,'Twister') % for reproducibility
    [mse,nlearn] = cvshrink(ls,'lambda',ls.Regularization.Lambda,'kfold',5);
    
    figure;
    semilogx(ls.Regularization.Lambda,ls.Regularization.ResubstitutionMSE);
    hold;
    semilogx(ls.Regularization.Lambda,mse,'r--');
    hold off;
    xlabel('Lambda');
    ylabel('Mean squared error');
    legend('resubstitution','cross-validation','Location','NW');
    line([1e-3 1e-3],[ls.Regularization.ResubstitutionMSE(1) ...
         ls.Regularization.ResubstitutionMSE(1)],...
        'marker','x','markersize',12,'color','b');
    line([1e-3 1e-3],[mse(1) mse(1)],'marker','o',...
        'markersize',12,'color','r','LineStyle','--');
    
    figure;
    loglog(ls.Regularization.Lambda,sum(ls.Regularization.TrainedWeights>0,1));
    hold;
    loglog(ls.Regularization.Lambda,nlearn,'r--');
    hold off;
    xlabel('Lambda');
    ylabel('Number of learners');
    legend('resubstitution','cross-validation','Location','NE');
    line([1e-3 1e-3],...
        [sum(ls.Regularization.TrainedWeights(:,1)>0) ...
        sum(ls.Regularization.TrainedWeights(:,1)>0)],...
        'marker','x','markersize',12,'color','b');
    line([1e-3 1e-3],[nlearn(1) nlearn(1)],'marker','o',...
        'markersize',12,'color','r','LineStyle','--');

    交差検定誤差を調べると、1e-2 をわずかに超える地点までは、Lambda に対する交差検定の MSE がほとんど平坦であることが示されています。

  9. ls.Regularization.Lambda を検査し、平坦な領域 (1e-2 をわずかに超える地点まで) で MSE が検出されている最も高い値を探します。

    jj = 1:length(ls.Regularization.Lambda);
    [jj;ls.Regularization.Lambda]
    ans =
    
      Columns 1 through 6
    
        1.0000    2.0000    3.0000    4.0000    5.0000    6.0000
             0    0.0014    0.0033    0.0077    0.0183    0.0435
    
      Columns 7 through 10
    
        7.0000    8.0000    9.0000   10.0000
        0.1031    0.2446    0.5800    1.3754

    ls.Regularization.Lambda の要素 5 の値は 0.0183 であり、平坦な領域で最も大きな値を示しています。

  10. shrink メソッドを使用して集団のサイズを小さくします。shrink は学習データをもたないコンパクトな集団を返します。新しいコンパクトな集団の一般化誤差は、既に mse(5) の交差検定によって推定されています。

    cmp = shrink(ls,'weightcolumn',5)
    cmp = 
    
      classreg.learning.regr.CompactRegressionEnsemble
           PredictorNames: {1x25 cell}
             ResponseName: 'symboling'
        ResponseTransform: 'none'
                 NTrained: 15
    
    
      Properties, Methods

    新しい集団には 15 本のツリーしかないため、ls の 300 本と比較すれば、顕著に減少しています。

  11. 集団のサイズを比較します。

    sz(1) = whos('cmp'); sz(2) = whos('ls');
    [sz(1).bytes sz(2).bytes]
    ans =
    
           84544     1775691

    ツリー数を減少させた集団のサイズは、元の集団の約 5% です。

  12. ツリー数を減少させた集団と元の集団の MSE を比較します。

    figure;
    plot(kfoldLoss(cv,'mode','cumulative'));
    hold on
    plot(cmp.NTrained,mse(5),'ro','MarkerSize',12);
    xlabel('Number of trees');
    ylabel('Cross-validated MSE');
    legend('unregularized ensemble','regularized ensemble',...
        'Location','NE');
    hold off

    新しい集団では、大幅に少ないツリーを使用しながらも、損失を低く抑えています。

RobustBoost の調整

RobustBoost アルゴリズムは、学習データにノイズが存在する場合でも、優れた分類予測を実行できます。ただし、RobustBoost パラメーターを既定の設定で使用すると、予測精度が十分ではない集団が生成される可能性があります。この例では、予測精度を高めるためにパラメーターを調整する方法の 1 つを示します。

    メモ:   RobustBoost は Optimization Toolbox ライセンスが必要です。

  1. ラベル ノイズのあるデータの生成。この例では、観測値あたり 20 の一様乱数を使用しており、最初の 5 つの数字の合計が 2.5 を超えた場合 (つまり、平均より大きい場合) には、観測値を 1 に分類し、そうでない場合には、0 に分類します。

    rng(0,'twister') % for reproducibility
    Xtrain = rand(2000,20);
    Ytrain = sum(Xtrain(:,1:5),2) > 2.5;
  2. ノイズを追加するために、分類の 10% をランダムに入れ替えます。

    idx = randsample(2000,200);
    Ytrain(idx) = ~Ytrain(idx);
  3. 比較の対象とするために、AdaBoostM1 を使用して集団を作成します。

    ada = fitensemble(Xtrain,Ytrain,'AdaBoostM1',...
        300,'Tree','LearnRate',0.1);
  4. RobustBoost で集団を作成します。データの 10% は間違って分類されているため、この場合、15% という誤差の目標値は適切です。

    rb1 = fitensemble(Xtrain,Ytrain,'RobustBoost',300,...
       'Tree','RobustErrorGoal',0.15,'RobustMaxMargin',1);
  5. 誤差の目標値として高い値、0.6 を指定します。次のエラーが表示されます。

    rb2 = fitensemble(Xtrain,Ytrain,'RobustBoost',300,'Tree','RobustErrorGoal',0.6)
    
    Error using RobustBoost>RobustBoost.RobustBoost
    For the chosen values of 'RobustMaxMargin' and 'RobustMarginSigma', you must set
    'RobustErrorGoal' to a value between 0 and 0.5.

  6. 非常に楽観的な誤差の目標値 0.01 をもつ集団を作成します。

    rb2 = fitensemble(Xtrain,Ytrain,'RobustBoost',300,...
       'Tree','RobustErrorGoal',0.01);
  7. 4 つの集団の再置換誤差を比較します。

    figure
    plot(resubLoss(rb1,'mode','cumulative'));
    hold on
    plot(resubLoss(rb2,'mode','cumulative'),'r--');
    plot(resubLoss(ada,'mode','cumulative'),'g.');
    hold off;
    xlabel('Number of trees');
    ylabel('Resubstitution error');
    legend('ErrorGoal=0.15','ErrorGoal=0.01',...
        'AdaBoostM1','Location','NE');

    RobustBoost の曲線はすべて、AdaBoostM1 の曲線より低い再置換誤差を示しています。誤差の目標値が 0.15 の曲線は、ほとんどの範囲で最も低い再置換誤差を示しています。

  8. 検定データを生成して、集団の予測能力を確認します。4 つの集団をテストします。

    Xtest = rand(2000,20);
    Ytest = sum(Xtest(:,1:5),2) > 2.5;
    idx = randsample(2000,200);
    Ytest(idx) = ~Ytest(idx);
    figure;
    plot(loss(rb1,Xtest,Ytest,'mode','cumulative'));
    hold on
    plot(loss(rb2,Xtest,Ytest,'mode','cumulative'),'r--');
    plot(loss(ada,Xtest,Ytest,'mode','cumulative'),'g.');
    hold off;
    xlabel('Number of trees');
    ylabel('Test error');
    legend('ErrorGoal=0.15','ErrorGoal=0.01',...
        'AdaBoostM1','Location','NE');

    誤差の目標値が 0.15 の誤差曲線は、プロットの範囲では最も低い値 (最も精度が高い) であることを示しています。AdaBoostM1 は、誤差の目標値 0.15 の曲線より誤差が大きくなっています。過度に楽観的な誤差の目標値 0.01 の曲線は、プロットされたほとんどの範囲において、他の曲線よりも顕著に高い誤差 (低い精度) を示しています。

無作為な部分空間の分類

次の例は、無作為な部分空間集団を使用して分類の精度を向上させる方法を示しています。また、交差検定を使用して、弱学習器テンプレートと集団の両方に適切なパラメーターを判別する方法も示します。

1. データを読み込みます。

ionosphere データを読み込みます。このデータには 34 の予測子に対する 351 のバイナリ応答が含まれます。

load ionosphere;
[N,D] = size(X)
N =
   351

D =
    34
resp = unique(Y)
resp =
    'b'
    'g'

2. 最近傍の数を選択する。

交差検定を実行して、分類器における最近傍の数 k の適切な選択を見つけます。対数スケールでほぼ等間隔にある近傍の数を選択します。

rng(8000,'twister') % for reproducibility
K = round(logspace(0,log10(N),10)); % number of neighbors
cvloss = zeros(numel(K),1);
for k=1:numel(K)
    knn = ClassificationKNN.fit(X,Y,...
        'NumNeighbors',K(k),'crossval','on');
    cvloss(k) = kfoldLoss(knn);
end
figure; % plot the accuracy versus k
semilogx(K,cvloss);
xlabel('Number of nearest neighbors');
ylabel('10 fold classification error');
title('k-NN classification');

交差検定の誤差が最小なのは、k = 2 の場合です。

3. 集団を作成する。

さまざまな次元数をもつ 2 最近傍分類の集団を作成し、結果集団の交差検定損失を調べます。

この手順の実行には時間がかかります。進捗を追跡するには、各次元が終了するごとにメッセージを表示させます。

NPredToSample = round(linspace(1,D,10)); % linear spacing of dimensions
cvloss = zeros(numel(NPredToSample),1);
learner = ClassificationKNN.template('NumNeighbors',2);
for npred=1:numel(NPredToSample)
   subspace = fitensemble(X,Y,'subspace',200,learner,...
       'npredtosample',NPredToSample(npred),'crossval','on');
   cvloss(npred) = kfoldLoss(subspace);
   fprintf('Random Subspace %i done.\n',npred);
end
figure; % plot the accuracy versus dimension
plot(NPredToSample,cvloss);
xlabel('Number of predictors selected at random');
ylabel('10 fold classification error');
title('k-NN classification with Random Subspace');
Random Subspace 1 done.
Random Subspace 2 done.
Random Subspace 3 done.
Random Subspace 4 done.
Random Subspace 5 done.
Random Subspace 6 done.
Random Subspace 7 done.
Random Subspace 8 done.
Random Subspace 9 done.
Random Subspace 10 done.

1 つの学習器に 5 つの予測子をもつ集団は、交差検定誤差が最も小さくなります。約 0.06 の誤り率は個々の学習器の量 (0.10 以上) の約半分です。

4. 適切な集団サイズを求めます。

集団内で最も数が少なく、なおかつ適切な分類が可能な学習器を求めます。

ens = fitensemble(X,Y,'subspace',200,learner,...
       'npredtosample',5,'crossval','on');
figure; % plot the accuracy versus number in ensemble
plot(kfoldLoss(ens,'mode','cumulative'))
xlabel('Number of learners in ensemble');
ylabel('10 fold classification error');
title('k-NN classification with Random Subspace');

学習器が 150 を超える集団には利点がないと考えられます。学習器が 50 を超える場合に利点があるかどうかは明確ではありません。25 の学習器が含まれる場合に適正な予測ができる可能性があります。

5. 最終的な集団を作成する。

50 の学習器を使用して最終的な集団を作成します。集団をコンパクト化し、コンパクト化したバージョンでそれなりのメモリ量が節約されるかどうかを確認します。

ens = fitensemble(X,Y,'subspace',50,learner,...
       'npredtosample',5);
cens = compact(ens);
s1 = whos('ens');s2 = whos('cens');
[s1.bytes s2.bytes] % si.bytes = size in bytes
ans =
     2317803     2087370

コンパクトな集団は完全な集団に比べて約 10% 小さくなります。どちらの集合でも同じ予測が得られます。

TreeBagger の例

TreeBagger 集団には、fitensemble を使用して作成された集団よりも多くの機能があります。「fitensemble にはない TreeBagger の機能」を参照してください。また、一部のプロパティ名およびメソッド名は、対応する fitensemble のプロパティ名やメソッド名とは異なります。この節では、この TreeBagger 固有の機能を使用した回帰および分類のワークフローの例を示します。

ワークフローの例:TreeBagger を使用した車両輸入の保険リスク ランク付けの回帰

この例では、205 件の観測、25 の入力変数、および 1 つの応答変数である保険リスク ランク付け (つまりシンボル化) をもつ 1985 年の車両輸入のデータベースを使用します。最初の 15 個の変数は数値で、最後の 10 個はカテゴリです。シンボル インデックスは、-3 ~ 3 の整数です。

  1. データセットを読み込み、それを予測子と応答の配列に分割します。

    load imports-85;
    Y = X(:,1);
    X = X(:,2:end);
  2. バギングがランダム化されたデータ図を使用するため、その正確な結果はランダムな初期シードにより異なります。この例で正確な結果を再生するには、ランダム ストリーム設定を使用します。

    rng(1945,'twister')

最適なリーフ サイズを見つける-  回帰の場合、原則は、リーフ サイズを 5 に設定し、決定分割のための入力特徴の 3 分の 1 を無作為に選択することです。以下の手順で、さまざまなリーフ サイズを使用して、回帰によって取得された平均二乗誤差を比較することにより、最適なリーフ サイズを確認してください。oobError は、MSE と成長したツリーの数を計算します。後で out-of-bag 予測を取得するために、oobpred'on' に設定しなければなりません。

leaf = [1 5 10 20 50 100];
col = 'rgbcmy';
figure(1);
for i=1:length(leaf)
    b = TreeBagger(50,X,Y,'method','r','oobpred','on',...
			'cat',16:25,'minleaf',leaf(i));
    plot(oobError(b),col(i));
    hold on;
end
xlabel('Number of Grown Trees');
ylabel('Mean Squared Error');
legend({'1' '5' '10' '20' '50' '100'},'Location','NorthEast');
hold off;

赤い (リーフ サイズ 1) 曲線は最も低い MSE 値です。

特徴の重要性の推定-  

  1. 実際に応用する場合、数百本のツリーで集団を成長させるのが普通です。高速で処理するために、「最適なリーフ サイズを見つける」では 50 本のツリーのみが使用されました。これで最適なリーフ サイズを推定したので、100 本のツリーでより大きな集団を成長させ、それを使用して特徴の重要性を推定してみましょう。

    b = TreeBagger(100,X,Y,'method','r','oobvarimp','on',...
    'cat',16:25,'minleaf',1);
  2. エラー曲線を再び調べ、学習中に誤りがなかったことを確認します。

    figure(2);
    plot(oobError(b));
    xlabel('Number of Grown Trees');
    ylabel('Out-of-Bag Mean Squared Error');

予測機能は、些細な特徴ではなく、より重要な特徴に依存しなければなりません。このアイデアを使用して、特徴の重要性を計測することができます。

データセット内のすべての観測全体で、各特徴に対してこの特徴の値を並べ替えることができます。並べ替え後に平均二乗誤差 (MSE) がどのくらいより悪くなるかを計測することができます。特徴ごとにこれを繰り返すことができます。

  1. 以下のコードを使用して、各入力変数全体の out-of-bag 観測値の並べ替えが原因による MSE 内の増加を曲線で示します。OOBPermutedVarDeltaError 配列は、変数ごとに集団内のすべてのツリーで平均化し、ツリーから取得した標準偏差で割った MSE の増加を格納します。この値が大きいほど、変数はより重要になります。0.65 で任意のカットオフを課して、5 つの最も重要な特徴を選択することができます。

    figure(3);
    bar(b.OOBPermutedVarDeltaError);
    xlabel('Feature Number');
    ylabel('Out-Of-Bag Feature Importance');
    idxvar = find(b.OOBPermutedVarDeltaError>0.65)
    
    idxvar =
    
       1    2     4     16    19

  2. TreeBaggerOOBIndices プロパティは、どの観測がどのツリーの out-of-bag であるかを追跡します。このプロパティを使用して、すべてのツリーにまとめられた学習データの観測割合を監視することができます。曲線は約 2/3 の地点 (1 つのブートストラップ複製により選択された固有の観測の割合) で開始し、約 10 本のツリーの地点で 0 に下がります。

    finbag = zeros(1,b.NTrees);
    for t=1:b.NTrees
        finbag(t) = sum(all(~b.OOBIndices(:,1:t),2));
    end
    finbag = finbag / size(X,1);
    figure(4);
    plot(finbag);
    xlabel('Number of Grown Trees');
    ylabel('Fraction of in-Bag Observations');

特徴の数を絞ってツリーを育てる-  特徴の重要性の推定 内で選択された最も強力な 5 つの特徴を使用して、同じような予測力を得ることができるかどうかを決定します。まず、これらの特徴のみで 100 本のツリーを育てます。選択した 5 つの特徴の 最初の 3 つは数値で、残りの 2 つはカテゴリです。

b5v = TreeBagger(100,X(:,idxvar),Y,'method','r',...
'oobvarimp','on','cat',4:5,'minleaf',1);
figure(5);
plot(oobError(b5v));
xlabel('Number of Grown Trees');
ylabel('Out-of-Bag Mean Squared Error');
figure(6);
bar(b5v.OOBPermutedVarDeltaError);
xlabel('Feature Index');
ylabel('Out-of-Bag Feature Importance');

この最強の 5 つの特徴にはフル セットと同じ MSE があり、減少したセットで学習された集団は、同じように互いにこれらの特徴をランク付けします。減少したセットの特徴 1 と 2 は、おそらく大きな損失なしに予測力に取り除けるでしょう。

外れ値を見つける-  学習データ内の外れ値を見つけるには、fillProximities を使用して、近接行列を計算します。

b5v = fillProximities(b5v);

標本全体に対する平均外れ値測定を減算し、この違いの大きさを取り、結果を標本全体に対する平均絶対偏差で除算することにより、メソッドはこの測定を正規化します。

figure(7);
hist(b5v.OutlierMeasure);
xlabel('Outlier Measure');
ylabel('Number of Observations');

データ内のクラスターを発見する-  多次元のスケーリングを類似度の計算行列に適用することにより、入力データの構造を検査し、観測の可能なクラスターを探すことができます。mdsProx メソッドは、計算近接行列のためにスケーリングされた座標と固有値を返します。colors オプションと併用すると、このメソッドは 2 つのスケーリングされた座標 (既定の設定では 1 番目と 2 番目) の散布図を作成します。

figure(8);
[~,e] = mdsProx(b5v,'colors','k');
xlabel('1st Scaled Coordinate');
ylabel('2nd Scaled Coordinate');

最初の 20 個の固有値をプロットすることにより、スケーリングした軸の相対的な重要性を評価します。

figure(9);
bar(e(1:20));
xlabel('Scaled Coordinate Index');
ylabel('Eigenvalue');

将来使用するために集団構成を保存する-  学習した集団を使用して未観測データの応答を予測する場合は、ディスクに集団を格納し、後でそれを取り出します。out-of-bag データの予測の計算や、他の方法による学習データの再利用を行わない場合は、集団オブジェクト自体を格納する必要がありません。その場合は、集団のコンパクトなバージョンを保存するだけで十分です。以下のように、集団からコンパクトなオブジェクトを抽出します。

c = compact(b5v)

c = 

Ensemble with 100 decision trees:
Method:           regression
Nvars:                    5

これでこのオブジェクトは通常どおり *.mat ファイルに保存することができます。

ワークフローの例:TreeBagger を使用したレーダーが返す電離層データの分類

また、分類用に決定木の集団を使用することができます。この例の場合は、351 回の観測と 34 個の実数値の予測子をもつ電離層データを使用します。応答変数は、以下の 2 つのレベルをもつカテゴリです。

  • 'g' は良質のレーダー応答

  • 'b' は悪質のレーダー応答

目標は、34 回の測定のセットを使用して、応答の良し悪しを予測することです。ワークフローは、「ワークフローの例:TreeBagger を使用した車両輸入の保険リスク ランク付けの回帰」とよく似ています。

  1. ランダム値を生成するための初期シードを固定し、50 本のツリーを成長させ、集団エラーがツリーの累積と交替する様子を調べ、特徴の重要性を推定します。分類するための最良の方法は、最小のリーフ サイズを 1 に設定し、無作為に分割した決定ごとに特徴の総数の平方根を選択することです。これは分類に使用される TreeBagger の既定の設定です。

    load ionosphere;
    rng(1945,'twister')
    b = TreeBagger(50,X,Y,'oobvarimp','on');
    figure(10);
    plot(oobError(b));
    xlabel('Number of Grown Trees');
    ylabel('Out-of-Bag Classification Error');

  2. この方法では、観測するツリーがほとんどない集団が学習されます。すべてのツリーに対して観測は in-bag です。このような観測では、真の out-of-bag 予測を計算することは不可能であり、TreeBagger は分類用に最も確からしいクラスを返し、回帰用に標本平均を返します。DefaultYfit プロパティを使用して、in-bag 観測用に返される既定値を変更することができます。分類用の既定値を空の文字列に設定すると、out-of-bag のエラーの計算から in-bag の観測が除外されます。この例では、ツリーの数が少ないと、曲線はより可変になります。理由は、観測によっては out-of-bag にならないこと (そのため除かれること)、または、ツリーの存在なしに予測するからです。

    b.DefaultYfit = '';
    figure(11);
    plot(oobError(b));
    xlabel('Number of Grown Trees');
    ylabel('Out-of-Bag Error Excluding in-Bag Observations');

  3. TreeBaggerOOBIndices プロパティは、どの観測がどのツリーの out-of-bag であるかを追跡します。このプロパティを使用して、すべてのツリーにまとめられた学習データの観測割合を監視することができます。曲線は約 2/3 の地点 (1 つのブートストラップ複製により選択された固有の観測の割合) で開始し、約 10 本のツリーの地点で 0 に下がります。

    finbag = zeros(1,b.NTrees);
    for t=1:b.NTrees
        finbag(t) = sum(all(~b.OOBIndices(:,1:t),2));
    end
    finbag = finbag / size(X,1);
    figure(12);
    plot(finbag);
    xlabel('Number of Grown Trees');
    ylabel('Fraction of in-Bag Observations');

  4. 特徴の重要性の推定

    figure(13);
    bar(b.OOBPermutedVarDeltaError);
    xlabel('Feature Index');
    ylabel('Out-of-Bag Feature Importance');
    idxvar = find(b.OOBPermutedVarDeltaError>0.8)
    
    idxvar =
    
         3     4     5     7     8

  5. 最も重要な 5 つの特徴を選択し、制限した特徴セットで、より大きな集団を成長させます。制限した特徴セットでは、out-of-bag 観測を変換せずに特徴の重要性の新しい推定を取得することにより、時間を節約します (oobvarimp'off' に設定)。分類エラーの out-of-bag 推定を取得することにしましょう (oobpred'on' に設定)。

    b5v = TreeBagger(100,X(:,idxvar),Y,'oobpred','on');
    figure(14);
    plot(oobError(b5v));
    xlabel('Number of Grown Trees');
    ylabel('Out-of-Bag Classification Error');

  6. 分類集団の場合は、分類エラー (誤って分類された観測の割合) に加えて、平均分類マージンを監視することもできます。観測ごとに、margin は、真のクラスのスコアおよびこのツリーが予測する他のクラスの最大スコアの差として定義されます。累積分類マージンはすべてのツリー全体の平均スコアを使用します。平均累積分類マージンはすべての観測全体の平均累積マージンです。'cumulative' (既定の設定) に設定された 'mode' 引数をもつ oobMeanMargin メソッドは、集団が成長するにつれて平均累積マージンが変わる様子を示します。返された配列内のすべての新要素は、新しいツリーを集団に含めることにより得た累積マージンを表します。学習が成功すると、平均分類マージンのゆるやかな増加が見えるはずです。

    決定木の場合、分類スコアは、ツリーのリーフにおけるクラスのインスタンスを観測する際の確率です。たとえば、成長した決定木のリーフがその観測を学習している 5 つの 'good' と 3 つの 'bad' をもつ場合は、このリーフになるすべての観測に対してこの決定木が返すスコアは、'good' クラスの 5/8 と 'bad' クラスの 3/8 です。これらの確率は、返された予測の数値に対して明白に翻訳できないような他の分類器との整合性を表す 'scores' と呼ばれます。

    figure(15);
    plot(oobMeanMargin(b5v));
    xlabel('Number of Grown Trees');
    ylabel('Out-of-Bag Mean Classification Margin');

  7. 類似度の行列を計算し、外れ値の測定の分布を見てください。回帰と異なり、分類集団用の外れ値の測定は、各クラス内で別々に計算されます。

    b5v = fillProximities(b5v);
    figure(16);
    hist(b5v.OutlierMeasure);
    xlabel('Outlier Measure');
    ylabel('Number of Observations');

  8. このデータセットのためのすべての極端な外れ値は以下の 'good' クラスから来ます。

    b5v.Y(b5v.OutlierMeasure>40)
    
    ans = 
    
        'g'
        'g'
        'g'
        'g'
        'g''
  9. 回帰と同じように、mdsProxcolors 引数を使用して、異なる色で 2 クラスを表示し、スケーリングした座標をプロットすることができます。この引数は文字列を取り、すべての文字は色を表します。集団が使用するクラスの順番は、ClassNames プロパティを見るとわかります。

    b5v.ClassNames
    
    ans = 
    
        'g'
        'b'

    'good' クラスが 1 つ目で 'bad' クラスが 2 つ目です。'good' の赤と 'bad' の青の観測を使用して、スケールした座標を表示します。

    figure(17);
    [s,e] = mdsProx(b5v,'colors','rb');
    xlabel('1st Scaled Coordinate');
    ylabel('2nd Scaled Coordinate');

  10. スケーリングにより取得した最初の 20 個の固有値をプロットします。この例では最初の固有値は明確に現れ、最初にスケーリングされた座標は非常に重要です。

    figure(18);
    bar(e(1:20));
    xlabel('Scaled Coordinate Index');
    ylabel('Eigenvalue');

分類性能曲線のプロット-  分類集団の性能を探究するもう 1 つの方法は、受信者動作特性 (ROC) 曲線または現在の課題に適する別の性能曲線をプロットすることです。まず、out-of-bag の観測値に対する予測を取得します。分類集団の場合、oobPredict メソッドは、1 つ目の出力引数として分類ラベル (電離層データ用の 'g' または 'b') のセル配列を返し、2 つ目の出力引数としてスコアの数値配列を返します。返されたステレオの配列はクラスごとに 1 列、合計 2 列になります。この場合、1 列目が 'good' クラスで 2 列目が 'bad' クラスです。スコア行列内の列の 1 つは冗長です。その理由は、スコアがツリーのリーフ内のクラス確率と合計 1 になる定義によるクラス確率を表すからです。

[Yfit,Sfit] = oobPredict(b5v);

perfcurve ユーティリティを使用して (詳細は「性能曲線」を参照)、性能曲線を計算します。既定の設定では、perfcurve は標準の ROC 曲線 (真陽性率対偽陽性率) を返します。perfcurve は、入力用に真のクラス ラベル、スコア、および陽性のクラス ラベルを必要とします。この例では、'good' クラスを陽性として選択します。このクラスのスコアは、Sfit の最初の列にあります。

[fpr,tpr] = perfcurve(b5v.Y,Sfit(:,1),'g');
figure(19);
plot(fpr,tpr);
xlabel('False Positive Rate');
ylabel('True Positive Rate');

標準の ROC 曲線の代わりに、たとえば、'good' クラスのためのスコアに集団精度対しきい値の座標をプロットするとよいでしょう。perfcurveycrit 入力引数により、y 軸の基準を指定することができます。perfcurve の 3 つ目の出力引数は、陽性のクラス スコアのためのしきい値の配列を返します。精度は正しく分類された観測の割合か、1 マイナス分類エラーと同じです。

[fpr,accu,thre] = perfcurve(b5v.Y,Sfit(:,1),'g','ycrit','accu');
figure(20);
plot(thre,accu);
xlabel('Threshold for ''good'' Returns');
ylabel('Classification Accuracy');

曲線は、0.2 ~ 0.6 のしきい値が妥当な選択であることを示す平らな領域を示します。既定の設定では、関数は、2 クラスの間で境界として 0.5 を使用し、分類ラベルを割り当てます。これがどの精度に対応するのかを正確に見つけることができます。

i50 = find(accu>=0.50,1,'first')
accu(abs(thre-0.5)<eps)

では、以下が返されます。

i50 = 
    2

ans =
    0.9430

最大限の精度は既定の精度よりやや高めです。

[maxaccu,iaccu] = max(accu)

では、以下が返されます。

maxaccu =
    0.9459

iaccu =
    91

したがって、最適なしきい値は、以下のようになります。

thre(iaccu)

ans =
    0.5056

集団アルゴリズム

AdaBoostM1

AdaBoostM1 は、二項分類のブースティング アルゴリズムとして一般的に利用されています。アルゴリズムでは、学習器に連続的に学習を行わせます。インデックス t をもつすべての学習器について、AdaBoostM1 は重み付き分類誤差を計算します。

ここで

  • xn は、観測値 n の予測子値のベクトルです。

  • yn は真のクラス ラベルです。

  • ht はインデックス t をもつ学習器の予測 (仮説) です。

  • はインジケーター関数です。

  • は、ステップ t での観測値 n の重みです。

AdaBoostM1 は、次に学習器 t によって誤判別された観測値の重みを増加させ、学習器 t によって正しく分類された観測値の重みを減少させます。次の学習器 t + 1 は、更新された重み をもつデータで学習を行います。

学習が完了した後で、AdaBoostM1 は次の式を使用して新しいデータの予測を計算します。

ここで以下のようになります。

は、集団に存在する弱仮説の重みです。

AdaBoostM1 による学習は、指数損失の逐次最小化と見なすことができます。

ここで、

  • yn ∊ {–1,+1} は真のクラス ラベルです。

  • wn は最大で 1 まで正規化される観測値の重みです。

  • f(xn) ∊ (–∞,+∞) は予測された分類スコアです。

観測値の重み wn は、fitensemble に渡した元の観測値の重みです。

AdaBoostM1 分類集団の predict メソッドの 2 番目の出力は、2 つのクラスと N 個の観測値の N 行 2 列の行列です。この行列の 2 列目は、常に最初の列の符合をマイナスにした値に等しくなります。predict はマルチクラス モデルと一致した 2 つのスコアを返します。ただし、2 番目の列は常に最初の列の負数になるため、これは冗長です。

AdaBoostM1 が最もよく使用されるのは、木の決定株 (既定の設定) または浅いツリーで使用される場合です。ブースティングされた決定株の性能が低い場合は、最小親ノード サイズを学習データの 4 分の 1 に設定します。

既定の設定では、ブースティング アルゴリズムの学習率は 1 です。学習率を低い値に設定した場合には、集団の学習率は低くなりますが、最終的には良い結果が得られます。最もよく使用される学習率は、0.1 です。1 より低い学習率を使用することは、“縮小推定” と呼ばれる場合があります。

AdaBoostM1 の使用例は、「RobustBoost の調整」を参照してください。

AdaBoostM1 に関連する参考資料は、Freund と Schapire [9]、Schapire など[15]、Friedman、Hastie、Tibshirani [11]、および Friedman [10]を参照してください。

AdaBoostM2

AdaBoostM2 は、複数クラスに対応するために拡張された AdaBoostM1 です。重み付き分類誤差の代わりに、AdaBoostM2 では、N 個の観測値と K クラスに対して、重み付き疑似損失を使用します。

ここで、

  • ht(xn,k) はステップ t での学習器の予測における信頼性であり、0 (まったく信頼できない) から 1 (信頼性が高い) までの範囲のクラス k で表されます。

  • は、クラス k のステップ t での観測値の重みです。

  • yn は真のクラス ラベルで、K の値のいずれかになります。

  • 2 番目の合計は、真のクラス yn 以外のすべてのクラスを対象としたものです。

疑似損失の解釈は分類誤差より難しいですが、基本的概念は同じです。疑似損失は、集団内の任意の学習器の分類精度を測定するために使用できます。疑似損失は、通常は AdaBoostM1 の重み付き分類誤差と同じように動作します。ブースティングされた集団の最初のいくつかの学習器では、疑似損失の値は低くなります。その後、学習ステップが進むと、集団の学習速度は遅くなり、疑似損失値は 0.5 に接近するほどに増加します。

AdaBoostM2 の使用例は、「分類集団の作成」を参照してください。

AdaBoostM2 に関連する参考資料は、Freund と Schapire [9]を参照してください。

バギング

"バギング" (bagging) は "ブートストラップ集約" (bootstrap aggregation) の略で、アンサンブル学習の一種です。データセット上の決定木などの弱学習器をバギングするには、このデータセットのブートストラップ複製を数多く生成し、この複製上で決定木を成長させます。N からの N 観測を置換で無作為に選択することにより、各ブートストラップ複製を取得します(N はデータセット サイズです)。学習した集団の予測された応答を見つけるには、個々のツリーからの予測の平均を取ります。

バギングされた決定木は MATLAB R2009a で導入されており、TreeBagger と呼ばれます。関数 fitensemble を使用すれば、ブースティングと同じ方法でバギングできます。バギングされた決定木の集合、ClassificationBaggedEnsemble または RegressionBaggedEnsemble は、fitensemble によって返され、TreeBagger とほぼ同等の機能を提供します。TreeBagger と新しいフレームワークの相違点は、「fitensemble にはない TreeBagger の機能」で説明されています。

バギングは、再標本化されたバージョンのデータで学習器を学習することによって機能します。この再標本化は、通常は観測値のブートストラップによって行われます。つまり、N 個の観測値から、新しい学習器ごとに N 個を置換して選択します。さらに、集団のすべてのツリーでは、決定分割の予測子を無作為に選択できます。これは、バギングされた決定木の精度を改善するためによく使用される手法です。

既定の設定では、バギングされたツリーの最小リーフ サイズは、分類では 1に、また回帰では 5 に設定されます。通常、既定の設定のリーフ サイズを使用して成長したツリーは、非常に深くなります。これらは、集団の予測能力を高めるにはほとんど最適な設定です。多くの場合、予測能力を低下させずにリーフ サイズの大きなツリーを成長させることができます。そうすることによって、学習済み集団のメモリ使用量が少なくなるだけでなく、学習や予測の時間も短縮されます。

もう 1 つの重要なパラメーターとして、決定分割ごとに無作為に選択される予測子の数があります。分割が起きるごとにこの無作為な選択が行われるため、深いツリーには常に多くの分割が存在します。既定の設定では、このパラメーターは分類では予測子数の平方根に、また回帰では予測子数の 3 分の 1 に設定されています。

バギングされた決定木の特徴のいくつかは固有なアルゴリズムになります。置き換えによって N 観測値から N を抽出すると、決定木ごとに平均 37% の観測が省略されます。これが "out-of-bag" 観測です。それらを使用して、予測力と重要性を推定することができます。観測ごとに out-of-bag 予測を推定するには、この観測が out-of-bag になっている集団内のすべてのツリーからの予測を平均します。それから、この観測値の応答に対して、計算された予測を比較することができます。学習に使用されたすべての観測値の応答に対して out-of-bag の予測応答を比較することにより、平均 out-of-bag エラーを推定することができます。この out-of-bag の平均は真の集団エラーの不偏推定量です。また、一度に 1 つの変数または列全体にわたり、無作為に out-of-bag データを並べ替え、この並べ替えのせいで増加する out-of-bag エラーを推定することにより、特徴の重要性の out-of-bag 推定を取得することができます。増加がより大きいほど、特徴はより重要になります。そのため、バギングされた集団に検定データを供給する必要がありません。バギングの長所である学習プロセス中に取得する予測力と特徴の重要性の推定が信頼できるからです。

バギングされた決定木のもう 1 つの優れた特徴が近接行列です。2 回の観測がツリーの同じリーフに着地するたびに、その近接は 1 つ増大します。正規化する場合は、集団内のすべてのツリーに対するこれらの類似度を合計し、それをツリーの数で割ります。結果の行列は 1 と等しい対角要素と 0 ~ 1 の非対角要素で対称的です。この行列を使用して、多次元のスケーリングを通してデータ内の外れ値の観測を見つけ、クラスターを発見できます。

バギングの使用例は、以下を参照してください。

バギングに関連する参考資料としては、Breiman [3][4]、および[5]を参照してください。

TreeBagger とバギングされた集団の比較-  fitensemble は、TreeBagger オブジェクトの機能と (すべてではないが) ほとんど同じ機能をもつバギングされた集団を生成します。また、新しいバギングされた集団では、一部の関数名などでは異なる名前が使用されています。

fitensemble にはない TreeBagger の機能

機能TreeBagger のプロパティTreeBagger のメソッド
近接行列の計算ProximityfillProximities, mdsProx
外れ値の計算OutlierMeasure該当なし
予測子の重要度に関する out-of-bag 推定OOBPermutedVarDeltaError, OOBPermutedVarDeltaMeanMargin, OOBPermutedVarCountRaiseMargin該当なし
個別に学習させた 2 つの集団のマージ該当なしappend
並列計算による集団の作成名前と値のペア UseParalleltrue に設定該当なし

TreeBagger とバギングされた集団における名前の違い

機能TreeBaggerバギングされた集団
予測子ごとの分離基準の貢献度DeltaCritDecisionSplit プロパティpredictorImportance (分類) または predictorImportance (回帰) の最初の出力
予測子の関連付けVarAssoc プロパティpredictorImportance (分類) または predictorImportance (回帰) の 2 番目の出力
誤差 (誤判別の確率または平均二乗誤差)error メソッドと oobError メソッドが用意されています。lossoobLoss メソッド (分類)、lossoobLoss メソッド (回帰)
追加のツリーの育成と集団への追加growTrees メソッドresume メソッド (分類)、resume メソッド (回帰)
ツリーごとの分類マージンの平均meanMargin メソッドと oobMeanMargin メソッドが用意されています。edgeoobEdge メソッド (分類)

さらに、バギングされた分類集団の学習と予測には、2 つの重要な変更点があります。

  • TreeBagger に誤判別コスト行列を渡す場合は、この行列をツリーに沿って渡します。fitensemble に誤判別コスト行列を渡す場合には、この行列を使用してクラスの事前確率を調整します。その後で、fitensemble は調整された事前確率と既定のコスト行列をツリーに渡します。既定のコスト行列は、K クラスでは ones(K)-eye(K) です。

  • 新しいフレームワークの loss メソッドと edge メソッドとは異なり、TreeBaggererror メソッドと meanMargin メソッドでは、それぞれのクラスの事前確率について、入力観測値の重みを正規化しません。

GentleBoost

GentleBoost (Gentle AdaBoost としても知られています) では、AdaBoostM1LogitBoost の機能が結合されています。AdaBoostM1 と同様に、GentleBoost は指数損失を最小化します。ただし、数値最適化の設定は異なります。LogitBoost と同様に、すべての弱学習器は回帰モデルを応答値 yn ∊ {–1,+1} に近似します。そのため、GentleBoost は、複数レベルのカテゴリカル予測子をもつデータの二項分類にも利用できます。

fitensemble は集団オブジェクトの FitInfo プロパティに平均二乗誤差を計算して格納します。平均二乗誤差は次の式で求められます。

ここで以下のようになります。

  • は、観測値の重みで、最大 1 になるまで増分 t が加算されます。

  • ht(xn) は、応答値 yn に近似された回帰モデル ht の予測です。

個々の学習器の強度が弱くなるに従って、重み付けられた平均二乗誤差は 1 に近づきます。

GentleBoost の使用例は、「例:不等価な分類コスト」、「カテゴリカル レベルの数が多い分類」を参照してください。

GentleBoost に関連する参考資料は、Freund、Hastie、および Tibshirani [11]を参照してください。

LogitBoost

LogitBoost も二項分類に利用されることが多いアルゴリズムです。LogitBoostAdaBoostM1 と同じように動作しますが、二項式の逸脱度が最小になる点が異なります。

ここで、

  • yn ∊ {–1,+1} は真のクラス ラベルです。

  • wn は最大で 1 まで正規化される観測値の重みです。

  • f(xn) ∊ (–∞,+∞) は予測された分類スコアです。

二項式に逸脱度が発生すると、誤判別の程度が大きい観測値 (ynf(xn) が高い負の値になる観測値) に割り当てられる重みが低くなります。LogitBoost を使用すると、クラスが適切に分割されていないデータに対しても、AdaBoostM1 より高い平均精度を達成できます。

LogitBoost 集団の学習器 t は、回帰モデルを応答値に近似します。

ここで、

  • y*n ∊ {0,+1} は、(-1 ではなく 0 に) ラベルを付け直されたクラスです。

  • pt(xn) は、観測値 xn がクラス 1 になる確率を現在の集団で推定した値です。

ブースティングのステップを行うごとに回帰モデルを近似することによって、複数レベルのカテゴリカル予測子をもつデータの計算が飛躍的に有利になります。レベル数が L のカテゴリカル予測子があるとします。そのような予測子の最適な決定分割を求めるには、分類木では、2L–1 – 1 とおりの分割を検討する必要があります。回帰木では、検討する必要があるのは L – 1 とおりの分割だけです。そのため、処理時間はかなり短くなります。多くのレベルをもつカテゴリカル予測子では、LogitBoost の使用が推奨されます。

fitensemble は集団オブジェクトの FitInfo プロパティに平均二乗誤差を計算して格納します。平均二乗誤差は次の式で求められます。

ここで以下のようになります。

  • は、観測値の重みで、最大 1 になるまで増分 t が加算されます。

  • ht(xn) は、応答値 に近似された回帰モデル ht の予測です。

値 yn の範囲は –∞ ~ +∞ です。そのため、平均二乗誤差には、明確な限界がありません。

LogitBoost の使用例は、「カテゴリカル レベルの数が多い分類」を参照してください。

LogitBoost に関連する参考資料は、Freund、Hastie、および Tibshirani [11]を参照してください。

LPBoost

LPBoost (線形プログラミング ブースティング) は、TotalBoost と同様に、トレーニング セットの最小 "マージン" の最大化を試行することにより、マルチクラス分類を実行します。この試行では最適化アルゴリズム (具体的には LPBoost の線形計画法) が使用されます。そのため、LPBoostTotalBoost を使用するには Optimization Toolbox のライセンスが必要です。

分類のマージンは、真のクラスについて予測されたソフト分類 "スコア" と、偽のクラスの最大スコアの差を表します。ツリーの場合、葉ノードの分類の "スコア" は、そのノードでの分類の事後確率です。あるノードにおける分類の事後確率とは、分類によって実際にそのノードに達するのに要した学習シーケンスの数を、そのノードまでの学習シーケンスの数で除算した値です。詳細は、margin定義 を参照してください。

最小マージンを最大化するのはなぜでしょうか。まず、一般化誤差 (新しいデータでの誤差) は負のマージンが発生する確率です。Schapire と Singer [16] は、負のマージンが発生する確率に関して次のような不等式を確立しました。

ここで、m はマージン、θ は任意の正の数値、V は分類器空間の Vapnik-Chervonenkis 次元、N は学習セットのサイズ、δ は正の少数です。この不等式は、多数の独立同一分布の学習セットとテスト セットに対して確率が 1–δ の場合に成立します。この不等式からわかることは、一般化誤差を小さくするには、トレーニング セットで観測数をマージン θ より小さく最小化します。

LPBoost は、一連の線形プログラミングの問題によって最小マージンの最大化するよう反復します。同様に、その双対性から、LPBoost は最大 "エッジ" を最小化します。エッジとは重み付けされた平均マージンです (「定義」を参照してください)。反復を実行するたびに、問題の制約が増えていきます。そのため、大きな問題に対しては、最適化の問題の制約が非常に多くなり、解決に時間がかかることになります。

LPBoost は通常、重み付けされた多数の学習器をもつ集団を作成します。この重みは、他の学習器の桁数より小さい桁数です。そのため、重要でない集団のメンバーをより確実に削除できるようにするため、compact メソッドでは LPBoost 集団のメンバーを重みの大きい順に並べ替えられます。これにより、removeLearners メソッドを使用して、重要性が最も低いメンバーを集団から簡単に削除できるようになります。

LPBoost の使用例は、「小さい集団での LPBoost と TotalBoost」を参照してください。

LPBoost に関連する参考資料は、Warmuth、Liao および Ratsch [18]を参照してください。

LSBoost

LSBoost (最小二乗ブースティング) は回帰集団の近似に使用します。ステップごとに、集団は新しい学習器を、実際に観測された応答とこれまでに学習させたすべての学習器を対象に集約された予測との差分に近似します。集団は近似によって平均二乗誤差を最小化します。

LearnRate パラメーターを渡すことによって、LSBoost を縮小推定で使用できます。既定の設定では、このパラメーターは 1 に設定されており、集団は最大速度で学習を行います。LearnRate0 から 1 までの値に設定した場合は、集団はすべての新しい学習器を yn – ηf(xn) に近似します。ここで、

  • yn は、観測された応答です。

  • f(xn) は、これまでに観測値 xn について学習を行ったすべての弱学習器から集約された予測です。

  • η は学習率です。

LSBoost の使用例は、「回帰集団の作成」、「例:回帰集団の正則化」を参照してください。

LSBoost に関連する参考資料は、Hastie、Tibshirani、および Friedman [12]、第 7 章 (モデルの割り当てと選択) と 第 15 章 (ランダム森) を参照してください。

RobustBoost

AdaBoostM1LogitBoost などのブースティング アルゴリズムでは、ブースティングのステップごとに誤判別された観測値の重みを増加させます。これらの重みは非常に大きくなる可能性があります。その場合は、ブースティング アルゴリズムが少数の誤判別された観測値に集中して、学習データの大部分が無視されてしまう可能性があります。その結果、平均分類精度が低下します。

この場合には、RobustBoost を使用できます。このアルゴリズムでは、全データ分の重みを少数の誤判別された観測値に割り当ててしまうようなことはほとんど起こりません。そのため、優れた平均分類精度を達成できます。

AdaBoostM1LogitBoost とは異なり、 RobustBoost では、特定の損失関数を最小化することはありません。代わりに、一定のしきい値を超える分類マージンをもつ観測値の数を最大化します。

RobustBoost は、時間発展に基づいて学習を行います。アルゴリズムは、t = 0 から開始します。ステップごとに、RobustBoost は最適化問題を解いて、時間 Δt での肯定的なステップと、それに対応する学習データ Δm の平均マージンにおける肯定的な変更を行います。次の 3 つの条件のいずれかが真の場合に、RobustBoost は学習を停止し、終了します。

  • 時間 t が 1 に到達する。

  • Δt および Δm の更新によっては、RobustBoost が最適化問題の解を求めることができなくなる。

  • RobustBoost は、要求した数の学習器を作成できます。

RobustBoost の結果は、どのような終了条件でも使用できます。交差検定または独立したテスト セットを使用することによって、分類精度を推定します。

RobustBoost で得られる精度を高くするには、関数 fitensemble で次の 3 つのパラメーターを調整します。このパラメーターは RobustErrorGoalRobustMaxMargin および RobustMarginSigma です。RobustErrorGoal の値を 0 から 1 まで変化させることから始めます。RobustErrorGoal に使用できる最大値は、他の 2 つのパラメーターによって変化します。高すぎる値を指定した場合は、fitensemble はエラー メッセージを表示し、RobustErrorGoal に使用できる値の範囲を示します。

RobustBoost の使用例は、「RobustBoost の調整」を参照してください。

RobustBoost に関連する参考資料は、Freund [8]を参照してください。

RUSBoost

RUSBoost は不均衡なデータ (学習データの一部のクラスが他のクラスよりメンバー数がはるかに少ない) の分類に特に有効です。RUS は「Random Under Sampling」の略です。このアルゴリズムでは、N (学習データで最もメンバー数が少ないクラスのメンバー数) を標本化の基本単位として使用します。これよりメンバー数が多いクラスは、各クラスの観測値の中から N 件だけを抽出してアンダーサンプリングされます。つまり、クラス数が K の場合、集団内の弱学習器のそれぞれについて、RUSBoost は K 個のクラスのそれぞれから N 件の観測値があるデータのサブセットを抽出します。ブースティングは「AdaBoostM2」の手順に従って実行され、集団の再度の重み付けと構築が行われます。

RUSBoost 集団を構築する場合、RatioToSmallest という名前のオプションの名前と値のペアがあります。K 個の値 (各値は割り当てられたクラスの標本数 N の倍数) があるベクトルを指定します。たとえば、最も小さいクラスのメンバー数が N = 100 の場合、RatioToSmallest = [2,3,4] は各弱学習器のメンバー数がクラス 1 では 200、クラス 2 では 300、クラス 3 では 400 であることを表します。RatioToSmallest が特定のクラスのメンバー数より大きい値を導き出した場合、RUSBoost はメンバー数を置き換えて標本化します。それ以外の場合、RUSBoost はメンバーを置き換えずに標本化します。

RUSBoost の使用例は、「不均衡データでの分類」を参照してください。

RUSBoost に関連する参考資料は、Seiffert 他を参照してください。 [17].

部分空間

無作為な部分空間集団 (Subspace) を使用して、判別分析 (ClassificationDiscriminant) または k 最近傍 (ClassificationKNN) 分類器の精度を向上させます。また、Subspace 集団はすべての予測子をもつ集団よりも少ないメモリを使用し、さらに欠損値 (NaN) も処理できます。

基本の無作為部分空間アルゴリズムでは以下のパラメーターを使用します。

  • m は各学習器で標本を取り出す次元 (変数) の数です。m の設定には名前と値のペア NPredToSample を使用します。

  • d はデータ内の次元数で、X データ行列の列 (予測子) の数を示します。

  • n は、集団内に存在する学習器の数です。NLearn を入力して n を設定します。

基本の無作為部分空間アルゴリズムは以下の手順を実行します。

  1. m 予測子の無作為なセットを置き換えなしに d の候補値の中から選択します。

  2. m 個の選択された予測子のみを使用して、弱学習器を学習させます。

  3. 弱学習器が n になるまで、手順 1 と 2 を繰り返します。

  4. 弱学習器の score 予測を平均して予測し、score の平均が最も高いカテゴリを分類します。

d の次元から選択可能なすべての m 個の予測子のセットで、弱学習器が作成されるよう選択できます。これを行うには、学習器の数を示す n を 'AllPredictorCombinations' に設定します。この場合、集団内には nchoosek(size(X,2),NPredToSample) の弱学習器が存在します。

関数 fitensemble は、後続の学習器が前に使用された予測子を使用する確率が下がるように、学習器の予測子を選択した後で予測子の重みを小さくします。このように重み付けを行うと、一様に重み付けするよりも学習器内の予測子が均等に分布される傾向をもちます。

Subspace の使用例は、「無作為な部分空間の分類」を参照してください。

ランダムな部分空間集団については、「Ho [13]」を参照してください。

TotalBoost

TotalBoost は、線形プログラミング ブースティング (LPBoost) と同様に、トレーニング セットの最小 "マージン" の最大化を試行することにより、マルチクラス分類を実行します。この試行では最適化アルゴリズム (TotalBoost の二次計画法) が使用されます。そのため、LPBoostTotalBoost を使用するには Optimization Toolbox のライセンスが必要です。

分類のマージンは、真のクラスについて予測されたソフト分類 "スコア" と、偽のクラスの最大スコアの差を表します。ツリーの場合、葉ノードの分類の "スコア" は、そのノードでの分類の事後確率です。あるノードにおける分類の事後確率とは、分類によって実際にそのノードに達するのに要した学習シーケンスの数を、そのノードまでの学習シーケンスの数で除算した値です。詳細は、margin定義 を参照してください。

最小マージンを最大化するのはなぜでしょうか。まず、一般化誤差 (新しいデータでの誤差) は負のマージンが発生する確率です。Schapire と Singer [16] は、負のマージンが発生する確率に関して次のような不等式を確立しました。

ここで、m はマージン、θ は任意の正の数値、V は分類器空間の Vapnik-Chervonenkis 次元、N は学習セットのサイズ、δ は正の少数です。この不等式は、多数の独立同一分布の学習セットとテスト セットに対して確率が 1–δ の場合に成立します。この不等式からわかることは、一般化誤差を小さくするには、トレーニング セットで観測数をマージン θ より小さく最小化します。

TotalBoost は、"エッジ" (重み付きマージン) が特定の値より下であるという制約のもとで、現在の重み分布と初期の重み分布の間のカルバック・ライブラー ダイバージェンスのプロキシを最小限にします。このプロキシは、このダイバージェンスの 2 次展開です。

ここで、Δ は W(n) (現在の反復と次の反復の重み) と W0 (初期の重み分布。一様分布です) の差を表します。この最適化定式によって、重みは 0 になりません。反復を実行するたびに、問題の制約が増えていきます。そのため、大きな問題に対しては、最適化の問題の制約が非常に多くなり、解決に時間がかかることになります。

TotalBoost は通常、重み付けされた多数の学習器をもつ集団を作成します。この重みは、他の学習器の桁数より小さい桁数です。そのため、重要でない集団のメンバーをより確実に削除できるようにするため、compact メソッドでは TotalBoost 集団のメンバーを重みの大きい順に並べ替えられます。これにより、removeLearners メソッドを使用して、重要性が最も低いメンバーを集団から簡単に削除できるようになります。

TotalBoost の使用例は、「小さい集団での LPBoost と TotalBoost」を参照してください。

TotalBoost に関連する参考資料は、Warmuth、Liao および Ratsch [18]を参照してください。

この情報は役に立ちましたか?