XGBoostで日経平均の株価を新聞からもとめる
はじめに
- Decision TreeのBoostingのRegressionは一度やっておこうと思った。
- 予想する問題に対して、素性の数が極めて大きい予想問題で、XGBoostの最適化手法を見ているとある程度、ロバストに動作するかもしれないという観測があり、今回のタスクは評価に適切だった
- 株を買って一山当てるのは、誰もが一度は夢見ることであろう
Boostingの基礎理論
非常に丁寧にかつよくまとまっているサイトがあるので、体系的に理解したい人は、リンクからたどると良です。
Gradient Boosting と XGBoost(今回、数式的な理解で大変参考にさせていただきました、ありがとうございます)
何をやっているかというと、弱い決定木を前の出力を次の出力に合算して、次の決定木に引き継がせているのだが、次の式で最小化すべき目的関数を再度構築している
N個のデータがあった場合、各データについてFという関数を仮定して、最小化していく問題とみなせる(ここはよくある問題設定)
t番目のデータを次のような微分が成り立つはずである
この微分をされている要素をyiとすると、次の値を最小化すれば良いことがわかる
これをT回反復を終えるまで回すとすると、次の式になる
Grandient Tree Boosting
Gradient Boostingを効率的に扱う式として、このような式が提案された
x_i, y~_iを最小化するような木を構築した後、 w_jをこの式を最小化するのだが、この式が解析的に解ける場合
これを最小化すればいい
Learning Rate
このような式で更新するのだが、ηが学習率に相当して、0.01~0.005がよいということになている。
Newton Boosting
最小化に使うアルゴリズムはGradient DescentではなくてNewton法を用いる
この式を直接最小化する
二次近似するとこのようになる
これで、f_T(x_i)を求めることが可能になる
XGBoost
Tは回帰儀、wは葉の重み
この式を近似して回帰着を構築する
図解によるイメージ
Step By Step解説
step.1
新聞の記事を分かち書きにする
$ python3 deal.py --step1
step.2
単語をindex化する
$ python3 deal.py --step2
step.3
日経平均のデータから目的となる数字を計算する
$ python3 deal.py --step3
step.4
XGBoost(バイナリ)で読める形に変換します
$ python3 deal.py --step4
なお、次の日のKPIを予想するのにこのようなオプションも使えます
$ python3 deal.py --step4alt
step.5
教師データとテストデータに分割します
$ python3 deal.py --step5
step.6
学習します
$ python3 deal.py --step6
step.7
モデルをダンプします
$ python3 deal.py --step7
step.8
f値を出力します
f値は何回判別の基準となる素性として選択されたかで、その事象を説明する大きさを示しはしませんが、その組成で決定木を作ると、うまく切れるということを示しています。
$ python3 deal.py --step8 | less
結果
4年分ぐらいのデータに関して、検証を行いました。
8割を学習用データ、2割をテストデータとして、ランダムに分割したものです
ROUND300, max_depth=3000000, eta = 0.025, regresion:linearでRSMEと呼ばれる誤差は980程度まで下げることができました。
悪くないように見えますが、どのような素性が反応しているのでしょうか、見てみましょう。
。 517.0
私 307.0
2015年 286.0
月 269.0
する 245.0
なっ 229.0
2012年 175.0
05 165.0
・ 164.0
さ 155.0
2017年 151.0
よう 145.0
た 144.0
2011年 141.0
( 131.0
2013年 128.0
優勝 120.0
粘り 118.0
いう 113.0
02 112.0
日 109.0
せ 104.0
2 104.0
で 103.0
04 101.0
い 96.0
2016年 92.0
...
しょうもない素性に反応しているのがよくわかりますね
確かに、年によるトレンドはあるので、何か商品やサービスが流行ると言うより、年代によるトレンドの変化に見えます。
ちなみに、名詞だけで行ったらどうなるのでしょうか。
名詞だけでXGBoostで回帰する
精度だけ見るとずっと落ちてしまうことがわかりました
rmseも1500ぐらいまでしか下がりません
反応する素性はこのようになっております
告示 57.0
おり 57.0
市 56.0
よ 55.0
注文 55.0
学校 54.0
面接 54.0
万 54.0
面 54.0
思い 53.0
元 53.0
黄身 52.0
的 52.0
指定席 52.0
合わせ 51.0
なり 50.0
...
企業名がおおくでるかと思いましたが、そのようなことはないようです。
自己回帰のように予想する
つまり、前日までの株価が既知だとします。
前日までの情報がわかっていれば、何らか簡単に次の日の株価を新聞の情報と加えて予想することができそうです
F(n)はn日の予想株価
Rはn日の実測値
Sはn日の新聞紙面
F(n) = R(n-1) + S(n-1)
つまり、これを予想するタスクとします。
RMSEは200程度まで下がることを確認しました。
つまり、平均200円前後しか、ずれずに予想できると言うことです。
一番性能が良いモデルです。
__SELF_PREV__ 18957.0
dBanner 515.0
中 340.0
以上 119.0
の 112.0
前 104.0
近道 78.0
ば 73.0
や 72.0
まし 62.0
米 60.0
い 50.0
化 50.0
よう 49.0
ページ 47.0
面倒 46.0
領収書 46.0
異例 45.0
者 44.0
感じ 43.0
ます 39.0
私 37.0
さ 37.0
一方 37.0
さん 36.0
宙 35.0
へ 35.0
なり 34.0
...
うーん、ライターの書く記事のボキャブラリーのズレを見ているような気がします。(つまり、文章の内容でなくて、書き手は年代で変わるので、それを特徴としている)
ちなみに、前日のデータだけでやってみましょう。
前日の株価から次の日の株価を予想する
新聞の素性を削り取り、翌日の株価を当てに行くと、簡単にフィットすることがわかりました。
しかも、精度も悪くないです...
RMSE200程度(日に200円程度しかずれない)
え、新聞の情報なくてもいけますね...
結論
新聞のコンテンツから、予想することもできるが、自己回帰予想が良さそうに見えるけど、新聞を入れても変わらないので、新聞は特徴量として役不足感がある。
xgboostのチューニングやアルゴリズムを工夫して、素性選択を頑張るなど、大量の素性を入れていくことで精度を上げて行くほうが筋が良いように見ます。
日経新聞、インターネット記事などをとにかく量を放り込んで予想するのがよいのかなぁって思ってます(かなり長い期間必要ですが)
自動売買プログラムでは、買うタイミングと売るタイミングが分かればよいから、別の問題になるがそういうタスクでは有効かもしれない。
fscoreはレグレッションなどにおいて、大きいほど主要因を占めるものというわけでない
fscoreは、何回決定木の決定要素になったかをかを、定量的に確認するものであり、レグレッションのタスクにおいて数が大きいからその問題において主要な影響力を持つというわけではありません
一回しか選択されなくても全体を説明してしまうこともあれば、何回も選択されているのに、重要な影響力を持つわけでなく、微細な調整に使われる素性もあります
つまり、今回の株価予想において株価は上がったり下がったりするのですが、そういう変化を表す素性として企業名だったり、その時の経済の状況だったりは重要な素性になりうるはずですが、日付によく反応してしまうことからも、日経平均は大雑把に丸められすぎてて、一企業の影響力が現れにくいような状態になっていそうです
p値とのこのfscore(決定木における特徴量重要度)に関して、調べたかたがいらっしゃったのでご紹介いたします。[1]
コード
参考文献
[1] ランダムフォレスト系ツールで特徴量の重要度を測る
[2] Gradient Boosted Tree (Xgboost) の取り扱い説明書
[3] Gradient Boosting と XGBoost