データの前処理
まずデータの前処理では、難なくRのrandomForestに突っ込むための加工を施します。主なステップは以下の4つです。
1. データのサンプリング
初期分析の段階で全データを使う必要はないと考えます。変数のサイズにもよりますが、私は10%くらいのデータでまずやるようにしています。
2. 数値型の変数の欠損値は中央値で補完。さらに、欠損の有無そのものを新たな変数とする
RのrandomForestのデフォルト設定では、欠損値があると実行できません。そのため、欠損値を補完する必要があります。
数値データの欠損は、本来は理由に応じて処理すべきですが、理由がわからなければ中央値で補完してしまいます。しかし、ただ単に補完してしまうと、数値が入っていたのか、欠損値だったかという情報が失われてしまいますので、欠損の有無をTRUE/FALSEで表現し、新たな変数として用意します。
3. 因子数が4つ以上のfactor型の変数は整数に変換
Rにはfactor(因子)と呼ばれるデータ型があり、カテゴリ変数を表現するのに使われます。
RのrandomForestパッケージは、因子数が多すぎるとエラーになるので、4つ以上の因子数があるfactor型の変数は、整数にしてしまいます。カテゴリ変数を整数に直してしまうと違う意味になってしまいますが、もしある特定の因子が精度に効いてくるのであれば、決定木の中でうまく探し当ててくれるはず!ということで乱暴ですが、整数にしてしまいます。
4. 日付は年、月、週数、1月1日からの経過日数、曜日などの数値の変数にばらす
日付はそのままだとランダムフォレストに入れにくいので、年、月、週数、1月1日からの経過日数、曜日といった数値に変換しておきます。
そしてランダムフォレストに突っ込む
さて、ここまでデータの前処理をしたら下のような感じで、データをランダムフォレストに突っ込みます。
randomForest(ind, dept, ntree=30, sampsize=5000, nodesize=20, do.trace=10))
#indが説明変数 deptは被説明変数です
ポイントは、sampsize、ntree、nodesizeを大きくしすぎないことです。
sampsizeは各決定木を作るときのサンプリング数ですが、これが大きいと学習に時間がかかります。
また、ntreeは決定木の個数を指定するパラメーターも大きくすると精度は上がりますが、時間もかかります。忙しい人にはそんなに待っていられません。そのため、木の数を30とか50とか小さくても良いと割りきったほうが学習は短時間で済みます。
最後のnodesizeは決定木のターミナルノードに残す最小レコード数を指定するパラメータですが、大きい数字にすると結果的には木は浅くなります。そのため、RのrandomForestパッケージのデフォルト設定では、分類問題であれば1、回帰問題であれば5ですが、これを比較的大きい数値(ここでは20)にすると木が伸び過ぎるのを抑えることができ、学習時間が短くなります。
変数の重要度を見る
RのrandomForestにはvarImpPlotという関数が用意されており、変数の重要度を簡単に確認することができます。
下の例は、Kaggleのbluebook-for-bulldozersという中古ブルドーザーのオークション落札価格を予測するというコンペのデータを使って、上記のデータ前処理を行い、varImpPlot関数で、変数の重要度を可視化したものです。
これを見ると、一目瞭然で重要度が高い変数がわかります。
例えば、一番上に出ている”YearMade”、つまり何年に作られたブルドーザーかを示す変数が重要であることがわかります。次いで、”ProductSize”、ブルドーザーの大きさも重要な変数のようです。
一方、グラフのしたのほうにある変数は重要度が低い変数です。このような変数は予測モデルを作るうえではあまり効かないので、モデルからはカットしてしまいます。
2つの変数を総当たりで割り算して新しい変数を作る
時間があるなら、分析者自身でどのような変数が効きそうかをイメージし、変数を新たに作ってモデリングするというのが正攻法ですし、そのほうが楽しいです。
しかし、時間がないとなるとそうも言ってられません。そこで、2つの変数を総当たりで割り算して新しい変数を作ってしまいます。この方法をとると、膨大な新しい変数が作られますが、ランダムフォレストに突っ込み、変数の重要度を見て、効いていない変数はモデルからどんどん除外していきます。そうすることで、モデルの精度を上げていくと同時に、どのような変数が重要なのかを理解していきます。
PartialPlotを使ってデータからインサイトを得る
分析コンペであればともかく、最終的にはデータから何がわかるのかを理解する必要があります。
そんなときは、RのrandomForestパッケージで用意されているpartialPlotという関数が役立ちます。
partialPlotとは、一言で言えば、偏微分です。興味ある特定の変数のみを動かし、残りの変数を固定したときの結果に与えるmarginal effect(限界効果)を可視化したものになります。
下の例は、再びKaggleのbluebook-for-bulldozersという中古ブルドーザーのオークション落札価格の予測コンペのデータを使ったものです。このコンペのトレーニングデータには、中古ブルドーザーの型式や製造年やスペックなど52の説明変数が用意されており、その中にはオークションの実施日付もありました。その日付から年だけを取り出した変数が、下のpartialPlotで用いた「saledate_year」という変数です。つまり、何年に行われたオークションかということですね。
さて、partialPlotの見方ですが、横軸が対象の変数、ここでは「saledate_year」です。縦軸が限界効用になります。このpartialPlotをみると、1990年代は高く、1990年代の最後になると価格が下がる傾向にあるようです。(1990年代は新品のブルドーザーが少なかった?1990年代前半は建築業界で需要が多かった?等いろいろな仮説が考えられますが、実際のところ調べていません。。。ご存知の方いましたら教えてください。)