Keras の LSTM で時系列の予測がしたい

深層学習で時系列の予測がしたいときとかあると思います。
以下の記事を参考にさせていただきます。
qiita.com

それで時系列データが手元にないので以下のサイトにある日経平均株価の日足をつかいます。
  日経平均株価 1時間足 時系列データ CSVダウンロード
直近1000営業日の値動きをプロットすると以下です。縦軸は学習のためにスケーリング済みです。

f:id:cookie-box:20170409085713p:plain:w700

以下のコードで学習します。参考記事のままです。前日まで10営業日分の株価を入力して当日の株価を予測するというモデルにします。900営業日分のデータで学習し、100営業日分のデータでテストすることにします。

# -*- coding: utf-8 -*-
import numpy
import pandas
import matplotlib.pyplot as plt

from sklearn import preprocessing
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.layers.recurrent import LSTM

# 学習用データを抽出する関数
def _load_data(data, n_prev=10):
  docX, docY = [], []
  for i in range(len(data) - n_prev):
    docX.append(data.iloc[i:(i+n_prev)].as_matrix())
    docY.append(data.iloc[i+n_prev].as_matrix())
  alsX = numpy.array(docX)
  alsY = numpy.array(docY)
  return alsX, alsY

if __name__ == "__main__":
  # 株価データの読み込み
  data = None
  for year in range(2007, 2018):
    data_ = pandas.read_csv('indices_I101_1d_' + str(year) +  '.csv')
    data = data_ if (data is None) else pandas.concat([data, data_])
  data.columns = ['date', 'open', 'high', 'low', 'close']
  data['date'] = pandas.to_datetime(data['date'], format='%Y-%m-%d')
  data['close'] = preprocessing.scale(data['close'])
  data = data.sort_values(by='date')
  data = data.reset_index(drop=True)
  data = data.loc[:, ['date', 'close']]
  data = data[1516:2515]

  # plt.plot(data['date'], data['close'])
  # plt.show()

  # 学習の設定
  length_of_sequences = 10
  in_out_neurons = 1
  hidden_neurons = 300

  # データ準備
  X_train, y_train = _load_data(data[['close']].iloc[0:900],    length_of_sequences)
  X_test,  y_test  = _load_data(data[['close']].iloc[900:1000], length_of_sequences)

  # ニューラルネットの定義
  model = Sequential()
  model.add(LSTM(hidden_neurons, \
            batch_input_shape=(None, length_of_sequences, in_out_neurons), \
            return_sequences=False))
  model.add(Dense(in_out_neurons))
  model.add(Activation("linear"))
  model.compile(loss="mean_squared_error", optimizer="rmsprop")

  # 学習
  model.fit(X_train, y_train, batch_size=100, nb_epoch=100, validation_split=0.05)

  # テスト結果表示
  predicted = model.predict(X_test)
  result = pandas.DataFrame(predicted)
  result.columns = ['predict']
  result['actual'] = y_test
  result.plot()
  plt.show()

テスト結果は以下です。当日の株価を予測するというか、前日をなぞっているだけですね。しかもなんかオフセットが付いているし。こんなの予測をしているといえない。知ってた。

f:id:cookie-box:20170409084531p:plain:w720

ネットワークに予測性能があるか確認するのに、もう少し「直前のN点から次の1点を予測できそう」な時系列をつかいたいです。そこで、R 組み込みの UKgas をつかいます。以下のようなデータです。四半期毎のデータなので周期性をもちます(冬はガス消費量が多く、夏は少ない)。
f:id:cookie-box:20170303235217p:plain:w700

以下の箇所以外さっきと同じコードで学習します。さっきは「直前までの10点から次の1点を予測」にしましたが、今回は四半期毎のデータなのでなんとなく4の倍数で12にします。UKgas は107点ありますが、最初の90点を学習につかい、最後の17点が予測できるかをテストします。

  length_of_sequences = 12
  in_out_neurons = 1
  hidden_neurons = 300

  X_train, y_train = _load_data(data[['gas']].iloc[0:90],    length_of_sequences)
  X_test,  y_test  = _load_data(data[['gas']].iloc[78:107], length_of_sequences)

  model.fit(X_train, y_train, batch_size=30, nb_epoch=100, validation_split=0.05)

テスト結果は以下です。予測結果も周期性をもっており、前回をなぞるだけではなく予測めいたことをしているようにはみえます。よかった。

f:id:cookie-box:20170409092832p:plain:w720

AAAI・WSDM 2017論文読み会: 参加メモ(途中)

AAAI・WSDM 2017論文読み会に参加させていただきました。
connpass.com
以下、自分の感想が入り混じったメモ。

GLOMA: Embedding Global Information in Local Matrix Approximation Models for Collaborative Filtering
 出典: http://chenkehan.me/papers/gloma_aaai17.pdf

  • 全アイテムの情報をぎゅっと凝縮しておいて、ユーザについて最適化する
  • 全ユーザの情報をぎゅっと凝縮しておいて、アイテムについて最適化する
  • サブグループにしてしまわず全部の情報をつかって最適化しているのがいいところ
  • これを確率的勾配降下で学習
    • ぎゅっと凝縮したやつも更新する
  • マルチタスク学習: 「算数のテストの成績」「100m走のタイム」を同時に学習する
  • サブグループの決め方(ユーザ数がすごいので k-means とかでは時間がかかりすぎる): DSDPというクラスタリング手法(k-means++ の 1000 倍速い)
    • 評価の星の数の頻度をつかう(?)
    • クラスタ初期化がランダムっぽいけどそんなに速い?

A Concise Integer Linear Programming Formulation for Implicit Search Result Diversification
 出典: http://www.dc.fi.udc.es/~roi/publications/wsdm2017-yu.pdf

  • SRD: ユーザがほしい情報をカバーするように多様な結果セットを返す手法
    • Ex. 「サーバル」と検索したときに、検索した人がほしい情報はネコ科の動物なのかアニメキャラなのか
  • 最適解にたどり着く implicit SRD の解法がほしい → 今回の提案法: ILP4ID
    • 整数線形計画問題にすることで従来法より最適値が得られる(分枝限定法)
    • DFP その他さまざまな implicit SRD の解法は ILP4ID の特別な場合に相当
    • 従来法はデータが大きくなるほどつかうのが危なくなる

Scalable Algorithm for Probabilistic Overlapping Community Detection

  • ソーシャルネットワークのような巨大なグラフ構造をクラスターに分割したい(overlapあり)
  • Bag-of-nodes 表現: 後々自然言語処理のようなことをしたいので、グラフ構造に Bag-of-words モデルに相当する表現を与えておく
  • Latent Dirichlet Allocation (LDA) を適用する(この手法の採用理由は決め打ち)
  • 従来手法だとデータセットが巨大だとそもそもメモリ的に実行できなかったり

Unimodal Thompson Sampling for Graph–Structured Arms
 出典: https://arxiv.org/pdf/1611.05724.pdf

  • 最適腕が存在するという強い仮定(unimodal)
  • 多腕バンディットタスクを解くのにグラフを利用
    • エッジは存在し、最良のノードへのエッジがどれかは不明
  • Thompson サンプリング: 以前以下の記事にメモした
  • 各腕をグラフのノードに対応させる
  • 限られた範囲で Thompson サンプリングを実行、最適腕に向かって登っていくようにする
  • 腕の数が多いとグラフを利用する意味がそこそこ出てくるらしい
  • この手法が有効なケースが限られる(腕の数、単峰性、…)

その他感想

「StanとRでベイズ統計モデリング」読書会#2: 参加メモ(途中)

水曜Stan - 「StanとRでベイズ統計モデリング」読書会#2に参加させていただきました。
spml4dm.connpass.com

勉強会メモ
今回は Chapter5(54〜78ページ)のもくもくでした。Chapter5 は基本的な統計モデルの紹介。
以下、大事だと思ったことのメモ。

重回帰:

  • 各推定対象パラメータの大きさが同程度(1程度)になるようにデータをスケーリングしておくといいかも。
  • MCMC に使用したデータの範囲外になる未知データに同じ事後モデルをそのまま適用するべきではない(使用データ範囲外では MCMC の結果が信用できるか全然わからないし、そのまま適用したら「出席率」がマイナスみたいな変なことになったりもするかも)。
  • モデルのあてはまりのよさを絵で確認するには、「観測値—予測値」プロットが y=x の周囲にあるか、MAP残差が想定した分散の正規分布にしたがっているかをみるとよい。

二項ロジスティック回帰:

  • 0〜1 をはみ出しちゃうっていうか出力が 0〜1 になるようにする。
  • (途中)

ロジスティック回帰:

  • (途中)

ポアソン回帰:

  • ポアソン分布は一時間に観測される流れ星の数みたいなやつ。
  • (途中)


「StanとRでベイズ統計モデリング」読書会: 参加メモ

水曜Stan - 「StanとRでベイズ統計モデリング」読書会に参加させていただきました。
spml4dm.connpass.com

勉強会メモ
Chapter1〜3 までの予習は前提で、勉強会では Chapter4 を各自もくもくという流れでした。
読んだページ: 28〜49ページ

  • 本には Windows へのインストール方法が書いてあるが、Mac へのインストールは以下の方の記事の通り。st-hakky.hatenablog.com
  • この本で示されているスクリプトは全て GitHub にある。
  • Stan のサンプリングアルゴリズムは NUTS(No-U-Turn Sampler)=ハミルトニアンモンテカルロ法の一種。
  • RStan によるパラメータ推定の手順(単回帰):
    • *.stan ファイルにモデルを記述する。
    • *.R ファイルでデータを読み込み、RStan に渡せる形式のリストに整え、モデルファイルとデータのリストを与えて stan() を実行する。
      • ステップ数の設定やデータを変更して何度も再実行する場合はモデルファイルでなくコンパイル済モデルのオブジェクトを渡すと速い。
  • chain: 「初期値と乱数の種をそれぞれ一つに定めて得られたサンプル列(13ページ)」。RStan のデフォルト設定では 4 chain のサンプル列生成が走る。各 chain を並列実行もできる。
  • thining(シンニング): MCMC においてサンプルを間引くこと。例えばサンプル列を1つおきに採用するなど。間引きによって収束が改善することがある。Stan のサンプリングではサンプル列の自己相関が低いので普通は間引かなくてよい。
  • 対数事後確率もパラメータ同様収束しなければならない。
  • 収束診断の作図には ggmcmc パッケージが便利。



2017-03-22 追記
読んだページ: 49〜53ページ

  • モデルにあらわれる変数を定義したり、MCMC 時に得られたサンプル列を利用してついでに計算しておきたい変数を定義したりできる。
    • transformed parameters ブロック: y := a * x + b のようにパラメータから新たな変数を定義できる。この y をモデル式につかえる。
    • generated quantities ブロック: y_new := a * x_new + b のように新たな変数を定義できる。例えばテキストのような年齢で年収を説明する例なら、未知の年齢の列を x_new にしておいて、未知の年齢群の年収の確率分布を得ることが考えられる。
      • 未知の x ではなく元データの x 列を x_new として、予測値(予測分布)の箱ひげ図(箱ひげ図じゃなくてもいいと思うけど)の上に実測値をプロットするような用途にもつかう(Chapter5)。「予測分布の上に実測値」式プロットはいつでも描けるので便利(説明変数が3つ以上のときは3次元プロットでも説明変数空間にはプロットできないから)。→ でも、62ページの図5.3をみるとごちゃついている気がするなあ…。
      • 2017-03-29 追記 モデル式を信頼区間の幅を持たせて書きたいとき便利(データのX列は 5, 10, 15 だったとき、信頼区間の幅をもったモデル式の図を得るには 5 と 10 の間の補間が必要)。

個人的宿題

その他

  • 48ページっぽい周辺分布の作図には ggExtra パッケージが便利らしい。

雑記

今日勉強会で、論文を読むのに、内容を1枚のスライドにまとめて数を何十本もこなすという話を聞きました。
同じ話が以下の記事に取り上げられています。論文1本にかける時間を切っておくのもコツみたいです。

lafrenze.hatenablog.com
自分は読みたいと思った論文は Dropbox に格納して永久に放置しているので、これをやってみたいです。
早速形から入ってみます(以下)。スーパー斜め読みなので内容は合っているかよくわからないです。
出典: https://openreview.net/forum?id=r1Ue8Hcxg

Neural Architecture Search with Reinforcement Learning
Barret Zoph, Quoc V. Le
どんなもの?
最終的に得るニューラルネット ( child network とよぶ ) の構造自体を RNN ( controller とよぶ ) を強化学習して決めさせる。
先行研究と比べてどこがすごい?
ニューラルネットの構造を探索する先行研究はない?
技術や手法のキモはどこ?
「よいニューラルネット構造を得る」を強化学習タスクとして定式化したところ。
child network の構造を可変長の文字列で表現することで controller RNN で生成できるようにしたところ。
どうやって有効だと検証した?
CIFAR10 などで人が設計したニューラルネットと比較。
議論はある?
この欄に書くことがよくわからないんだけど、この論文であればこういうケースは得意とかこういうケースは苦手とかいうのがくるのかもしれないけど、それもよくわからない。
次に読むべき論文は?
これの後発の論文だと思うけどまだ調べていない。
書いてみて思ったんだけど時間を切らないと精読しようとして進まないから時間を切るのはいいと思う。ただ上のフォーマットはしっくりこない。何かをつかんだ気がしない。なら自分用のフォーマットをつくるべきなんだけど、でも論文によってストーリーの抜き出し方は違うと思うんだけど、そうやってオーダーメイドしようとすると数がこなせないのか。難しい。