FastBDTでの高速化
はじめに
勾配ブースティング木の高速化はどうすればいいだろうと調べていたら、arxivで流れているのを見かけたのでメモ。
- FastBDT: A speed-optimized and cache-friendly implementation of stochastic gradient-boosted decision trees for multivariate classification
Stochastic Gradient Boosted Decision Tree(SGBDT)
- 勾配ブースティングの各イテレーションで、学習データから非復元抽出でサンプリングしたデータを用いる
- https://statweb.stanford.edu/~jhf/ftp/stobst.pdf
- 「統計的学習の基礎 データマイニング・推論・予測(共立出版)」だと、Importance sampled learning ensemble(ISLE)あたり?
- https://www.rco.recruit.co.jp/career/engineer/blog/32/
高速化
メモリアクセス、CPUキャッシュ、前処理、並列化を考慮。
メモリアクセスパターン
- 学習データのメモリ配置について最適化
- 一般的に以下の2つのレイアウト方式が考えられる
- array of structs(構造体の配列) : x_1, y_1, z_1, x_2, y_2, z_2, x_3, y_3, z_3, x_4, y_4, z_4
- struct of arrays(配列の構造体) : x_1, x_2, x_3, x_4, y_1, y_2, y_3, y_4, z_1, z_2, z_3, z_4
- FastBDTは「array of structs」を利用
- CPUキャッシュの空間的局所性(例:linear memory access pattern)、時間的局所性(小さなCPHのキャッシュ)、CPUの分岐局所性(conditional jumpをできるだけ避ける)を考慮
【正例と負例のメモリマップ】
- array of structsを利用する場合、そのまま並べてしまうと、正例と負例の判定で条件分岐が必要になってしまう
- そこで、正例と負例のデータを分けて、保存や処理を行う
【レイヤー毎の複数ノードの処理】
- ノード単位で別々にノードを処理していく方法だと、使用する学習データへのアクセスがとびとびになってしまい、メモリレイアウト方式によらずランダムにジャンプしてアクセスしてしまう
- (DFS的な感じでのノードの処理?)
- 木のレイヤー単位で、そのレイヤーすべてのノードを並列処理することができると、連続的なメモリアクセスにできる
【確率的サブサンプリング】
- SGBDTだと、学習データからサンプリングしたデータを使用するため、使うデータと使わないデータを選ぶ必要がある
- array of structsだと、各データポイントの範囲内であれば、条件分岐なしでデータへ連続的にアクセスできる