Nothing Especially

C言語とか

カーネル法で予測器を作ってみた。

全部説明するには余白が狭すぎるので式や説明は適当に流し読みしてください。

p次の線形予測フィルタは以下の式で表されます。
$$
s_n = \sum_{i=1}^p w_i s_{n-i}
$$
これをカーネル法によって次のように拡張します。
$$
s_n = \sum_{i=1}^p \alpha_i k({\bf{x}}^{(i)} , {\bf{x}})
$$
$$
k({\bf{x}}^{(i)} , {\bf{x}}) = exp(-\beta\| {\bf{x}}^{(i)} - {\bf{x}} \| ^ 2)
$$
\(i\)日前からある長さで過去に数日分の値動きを切り取ったものを\({\bf x}^{(i)}\)としています。
同じ長さで切り取った直近の過去の値動きが\({\bf x}\)です。

数日分の値動きを切り取ってベクトルにすると「パターン」として扱えますよね。
大雑把にいえば、そのパターンベクトルを\(p\)個保持し、そいつらと直近の値動きの差を測って、近いものから選んで重ね合わせて次の値を予測する、というニュアンスの式になっています。

漸化式的に繰り返し予測してベクトルを作りそれを\({\bf y}\)とおくとグラム行列\(K\)を用いて
$$
{\bf{y}} = K {\bf \alpha}
$$
と表せて、予測の二乗誤差を最小化するときにリッジ回帰で正則化してやるとカーネル法での計算式から
$$
{\bf \alpha} = (K + \lambda I_n)^{-1} {\bf y}
$$
となります。

説明は省略しますが「予測した値は正しい」という仮定を置くと予測誤差を最小化するようにカーネル法のハイパーパラメータ\(\beta\)が最急降下法を用いて計算できます。
$$
\beta' = \beta + 2 \gamma \sum_i \sum_j \frac{\partial {\bf k}({\bf x}) \cdot {\bf \alpha}} {\partial \beta} (s_{i+j-1} - {\bf k}({\bf x}) \cdot {\bf \alpha})
$$
ここが remarkable なポイントです!カーネル法では普通は\(\beta\)を最急降下法で計算することはできませんが、時系列データの予測に使う場合は例外的に最急降下法でいけるぜ、というのが今回の発見です。

試しに為替の値動きを学習して30日間予測したのが下図。青が実際の為替の値動きで赤が生成した予測値。

f:id:wsparrow:20170617202921p:plain

リッジ回帰の係数を\(\lambda=0.0005\)で固定し、\(\beta\)を適当に決めた(\(\beta = 0.005\))のが上のグラフ。そこから最急降下法で\(\beta\)の値を求めた(\(\beta = 0.0011897\))のが下のグラフ。予測値の一致率が大幅に改善してるのでうまくいってることがわかります。

予測したグラフはなんかちょっと上にズレてるが形は大体合ってる。つまり上昇とか下降の幅はともかくタイミングはそこそこ掴めてるってことですかね。実用には精度が全然足りないですけど。

ちなみに\(\lambda\)でも偏微分ができてその気になれば最急降下法が使えるのだが、当然のごとく\(\lambda = 0\)に収束する(オーバーフィッティングの状態になる)のでやる意味がない。

もし為替の値動きが1週間でも完璧に読めたらオレ超金持ちになれるんではとか思って割と本気出したけど世の中甘くない。

こいつを39ページまで理解してひと工夫すれば作れます。
カーネル多変量解析