時系列データの予測がしたい

時系列データというのは時刻など時間の何かがインデックスになってるデータのことだそうで、例えば毎日の平均気温とかがそうです。全くもってランダムだったりするかもしれませんが、気温のように

  • 24 時間周期とか 1 年周期で上がったり下がったりしながら
  • でも温暖化してるんじゃない? と上がっているような、氷河期に向かうときは下がっていくような
  • 隕石が落ちたり噴火があったりで空が何かで覆われると涼しく (寒く?) なったり
  • そもそも毎日の天気とかエルニーニョとか暑めだったり寒めだったり

  • 周期性 (複数あるかも、季節性とも)
  • 長期的なトレンド (温暖化とか氷河期とかは周期性かもしれませんが...)
  • 例外的なイベントによる外れ値的なものたち
  • 観測や環境によるノイズ

などの成分に分けて理解しようとするのが基本のようです。

予測をしようと思ったら、周期とトレンドはそのまま伸ばしてみつつ、例外的といってもバレンタインのチョコの売り上げとかは予測できる例外と思ってみたりトレンドの変更点も分かれば追加してみたりしつつ、未来のことを予測してみようというのが時系列の予測です。

どんなもんがあるのかなと思って少し調べてみたので、忘れないようにメモっておきます。

前処理

成長というのは倍々で起こることもあるので、そんなときは log を取ると真っ直ぐになって嬉しいです。漸化式のように、差を取ると分かりやすくなることもあるかもしれません。そんな感じで、与えられている数列を操作して別の数列を作ってそれで予測を立てて、逆の手順で欲しかった予測値を出すことがあります。「前処理大全」でも少し時系列データの前処理に触れられています。

AR-MA 系、若しくは ARIMA

AR は Autoregressor の、MA は Moving Average の略です。それぞれ、次の値は「過去の幾つかの値の線形結合 + ノイズになってる」、「過去のノイズの線形結合 + ノイズ」になっているという過程で線形結合の係数を探していくやりかたです。ノイズは正規分布を仮定して。

  • 前処理として 1 階差分を 1 回以上取るのを Integrated と言うらしく ARIMA と言ってみたり
  • 季節性 = Seasonality で複数階の差分を取って考えてみて SARIMA と言ってみたり
  • 外的要因 = eXterior regressor を考えて ARIMAX と言ってみたり
  • ノイズが大きさをダイナミックにしてみて (Conditional Heteroscedasticity) ARCH と言ってみたり
  • お互いに関係がありそうな複数の時系列をベクトルにして AR して VAR (Vector AR) と言ってみたり

色々なバリエーションがあります。詳しくは Wikipedia自己回帰移動平均モデルとかARCHモデルを。

例えば、アメリカセンサス局が作った X-12-ARIMA っていう実装があるらしく操作マニュアル日本銀行がウェブページに置いています。そんだけ古典的で枯れているということのようです。

時系列分析と状態空間モデルの基礎」という本が丁寧で分かりやすいでした。写経のし甲斐がある。

TRAMO-SEATS

スペイン銀行が作ったらしいです。X-12-ARIMA の後継で X-13ARIMA-SEATS というのがあるのですが、「季節調整法に関する最近の動向:X-12-ARIMA から X-13ARIMA-SEATS へ」によると ARIMA も TRAMO-SEATS もいけるようにしたもののようです。ヨーロッパ政府機関などでは TRAMO-SEATS が主流のようですね。使ってないのでこれ以上何も言えないのですが、「R {seasonal} パッケージで X13-ARIMA-SEATSを使う」とのことで R でもいけるみたいです。

状態空間モデル

状態空間という、予測したい値とは別に何か (多次元かもしれない) 時系列データを考えて、そっちの予測と状態から欲しかった観測値の関係のパラメータを探していくモデル。ARIMA と表現できるモデルが結構被っているみたいなんだけど、実際どこまで被っているのかは未確認。でも ARIMA と違って解釈は状態空間に意味を込めやすく楽らしい。ARIMA は過去のデータの線型結合を取りますが、それは確かに理解しづらそう。

1 つ制約があって、状態空間は直前の値にだけ依存するようにしています。マルコフ性、って言うのかな。

状態空間の遷移も状態からの観測も関数なら何でもいいんだけど、何でもいいと色々大変なので、線型に絞って考えることが多くそれでも色々良いみたい。状態遷移にも観測にもノイズを乗せるのですが、これも正規分布を仮定することが基本のようです。ただ、それだと表現力が限られたりもするのでそこから逸脱して、となると色々な方法を使わないと状態遷移・観測の関数の推測が難しくなっていって色々な方法が提案されています。「状態空間モデル」というフレームワークがあって、状態遷移・観測に応じて様々な関数推測の方法があるみたい。

状態空間モデルは「時系列分析と状態空間モデルの基礎」でも扱われていますが、「基礎からわかる時系列分析」だと数式てんこ盛りで、信号処理の話などを引用しつつ説明してくれています。

EWMA (Exponential Weighted Moving Average)

ごめんなさい、「基礎からわかる時系列分析」で Holt-Winters っていう方法が紹介されてて EWMA の一種だって書いてあったんです。名前からしてきっと Linux の load average と同じような計算しているに違いありません。というか、これは AR-MA に入れるべきか? 1つブログ記事を紹介してお茶を濁します: 異常検知のための未来予測:オウム返し的手法からHolt-Winters Methodまで

Wiener-filter

ごめんなさい、「基礎からわかる時系列分析」で Wiener-filter っていう方法が (ry。カルマンフィルタってのが状態空間モデルでの予測の方法で出てきますが、「フィルタ」って付いてるやつは信号処理由来のにおいがプンプンしますね。「やる夫で学ぶディジタル信号処理」がとてつもなく分かりやすくて感動しました。

ランダムフォレスト

ランダムフォレストで回帰ができるので、これで時系列予測しちゃいます。こんな感じで

Prophet

Facebook が作った、業務知識さえあれば使える、みたいなのを目指してるライブラリです。数値を見る、というよりは曲線をフィットさせる、という考えかた、らしい。「fb Prophet の解剖で学ぶベイズ時系列モデリング」で Stan による実装の話が紹介されています、素晴しすぎる。

実際、

  • 何も考えずに時系列データを入れるだけで「いい感じ」にやってくれ
  • トレンドの変換点も頻度指定ありで勝手に推測してくれたり細かい日付けの指定ができたり
  • 季節性も勝手に判断してくれたり強制させたり時前で好みの季節性指定できたり
  • 祝日なども複数の種類を簡単に指定して前後何日くらい影響があるか指定できたり

分かり易く色々なパラメータが指定できて良い感じでした。

DeepAR

Amazon の実装で、RNN (recurrent neural network) 使っています。近々、近々試そうと思っています。SageMaker 含めて。

実装

ARIMA・ランダムフォレスト・状態空間モデル・prophet は Python でも R で何かしら実装があります。prophet はどっちも結局 Stan への wrapper だそうですが、他のやつは実装によって色々挙動や調整のし易さが違いそうですね...。ARIMA とランダムフォレスト枯れているというか説明も沢山ありそうで prophet の次に手軽そうでした。

100% な予測はありえないので、コスパとか相性を見ながら良い方法が選べるといいですね!

EC2 四級講座

今更ですが、世に解説が溢れると自分でもやってみたくなるというのはデジャウ゛ではないでしょうか。しかし、ここに書かれていることを理解すれば四級合格も夢ではありません。四級合格に興味が無い人は http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/GettingStartedGuide/getting-started-ipv4.html を参考にさくっとインスタンスを作成しましょう。

EC2 は AWS でも比較的古いサービスです。AWS リージョン毎に複数のデータセンター群 (アベイラビリティーゾーン、AZ) があり、AWS のインフラ上で動く仮想マシーンを時間貸ししてくれます。古いので過去の歴史をいくらか引きずっています。昔は全てのユーザーのインスタンスが同じプライベート IP アドレス空間に存在していたのですが、VPC (Virtual Private Cloud) というサービスが登場してユーザーがプライベートなネットワークアドレス空間 (これのことも VPC と呼んじゃってます) を複数持てるようになりました。今ではこちらがふつーなので、以下では EC2-VPC のことだけ考えましょう。

EC2 インスタンスへのリソース割り当て

仮想マシーンなのでハイパーバイザーがいて

  • CPU
  • メモリ
  • ネットワークカード (NIC)
  • ディスク

などをインスタンスに提供してくれます。仮想化としては準仮想化と完全仮想化をサポートしてますが、近頃は完全仮想化が主流なので今後は完全仮想化だけ考えましょう。

CPU とメモリ

インスタンスのタイプを選ぶことで種類と量が決定されます。インスタンスタイプは沢山ありますが、先ずは T (tiny?) か、そうでなければ C (compute?) か M (memory?) を試してみるのが良いのではないかと思います。これらアルファベットが大まかなファミリーを表しており、数字は大きい方が新しいです。

NIC

2 種類用意されてるのですが、ふつー ENI (Elastic Network Interface) というのが最低 1 つ割り当てられます。性能はインスタンスタイプによって異なります。複数の ENI をインスタンスに付けることも可能ですが、増やしてもトータルの帯域が増えたりするわけではありません。VPC 的には ENI は、後述の VPC サブネット内の IP アドレスの確保という意味合いが強いです。プライマリなプライベートアドレスが VPCDHCP サーバーから割り当てられます。IPv6 も使えるようになりましたが、ここでは IPv4 の話だけ。(ふつーじゃない方は ENA (Elastic Network Adapter) なのですが、お値段の張るインスタンスタイプでだけ使えます)

ディスク

ハイパーバイザーの動くローカルハードウェアに載っているディスクとネットワークディスクの 2 つが使えます。ローカルの方をインスタンスストアと呼んでいて、インスタンスタイプによって数やサイズが異なります (1 つも付いてこないインスタンスタイプもあります)。インスタンスストアのお値段はインスタンス時間貸し料金に込み込みです。ネットワークディスクの方は EBS (Elastic Block Store) といいます。EBS もまた種類があり特性が異なります (現在 5 種類)。1 つあたり最大 16TiB までいけます。お値段はサイズや利用に応じて変わってきます。どちらも、インスタンスに複数アタッチでき、EBS ボリュームはインスタンスから外して付け直すなども可能です (アンマウントはしましょう)。インスタンスストアはバックアップなど自分で面倒を見る必要がありますが、EBS にはスナップショット機能があり AWS が S3 へのバックアップとリストアを面倒みてくれ、また冗長化もある程度されています。

EC2 インスタンスに対する基本の操作は以下の 4 つあるのですが (インスタンスのライフサイクル)、

このうち StopInstances と StartInstances は EBS ボリュームがルートボリュームとして指定されている EC2 インスタンスに対してのみ行えます。EC2 インスタンスが走っているホストは複数のユーザーにより共用されていて、止めたり消されたインスタンスはそのホスト上から一度居なくなり、空いたリソースを他のユーザーが使う可能性があります。ローカルディスクであるインスタンスストアが、停止されたインスタンスの用に維持されることもなく、一旦止めるという操作もできません。ルートボリュームが EBS であるインスタンスにもインスタンスストアを付けて利用することはできるのですが、Stop したあと Start すると新たにホストが割り当てられてインスタンスストアは真っ新なものが提供されます。

インスタンス作成の主要パラメータ

EC2 インスタンスを作るには RunInstances という API を呼び出します。「Request Parameters」という節に API のパラメーターが列挙されていますが、ふつー指定するのは下記の情報、でしょうか。

  • ImageId
  • InstanceType
  • KeyName
  • SecurityGroup
  • SubnetId
AMI

ImageId は、AMI (Amazon Machine Images) の ID を指定します。AMI は、ルートボリュームを含むディスクデータの参照情報 (ブロックデバイスマッピングと呼ばれています)、仮想化方法、ルートデバイス名などのメタ情報をまとめたものです。EBS ボリュームがルートの場合にはスナップショットの ID などが、インスタンスストアがルートの場合には S3 に置かれたデータへの参照情報がブロックデバイスマッピングに記載されているはずです。AMI は AWS で用意している Amazon Linux AMI の他、Red Hat Enterprise Linux, Ubuntu, CentOS など色々揃っています。Windows Server もあります。

インスタンスタイプ

InstanceType は、インスタンスタイプの名前を指定します。t2.xlarge とか。

RSA 鍵ペア

KeyName は、登録してある EC2 Key Pair を指定します。EC2 インスタンスには決してログインする必要はなく、色々作りこんだりすれば勝手に色々サービスを起動して Web サーバーになったり queue を処理するワーカーになったりするのですが、ログインしたい場合にインスタンスに認証情報を伝える 1 つの手段として EC2 Key Pair が用意されています。これは実際は RSA 公開鍵に名前を付けて登録してあるものです。

EC2 ではインスタンスの ID やプライベート・パブリック ID アドレスがインスタンス内部から参照できるように インスタンスメタデータ を提供しています。インターフェースとしては http://169.254.169.254/ を利用していて例えば

$ curl http://169.254.169.254/latest/meta-data/ami-id

とリクエストを投げると RunInstances で指定された AMI ID が取得できます。インスタンス作成時に指定された EC2 Key Pair の公開鍵も、作成されたインスタンスから http://169.254.169.254/ にアクセスすることにより取得可能です。Amazon Linux AMI を含め多くの AMI では cloud-init をそれぞれカスタマイズしてインストールしていて、インスタンス初回起動時には公開鍵をデフォルトユーザーの ~/.ssh/authorized_keys に自動で登録するようになってます。Windows の場合には、パスワードが自動生成のうえ公開鍵で暗号化されたものが提供されるので、秘密鍵で復号して RDP できるようになってます。

ログインなどの認証にもちろん SSH や RDP を使う必要もないし、ユーザーの設定がされた AMI からインスタンスを作成した場合には引き続きその認証情報が使えたり、起動時にやっぱりリセットされてしまうなどは、AMI の中身次第です。

セキュリティーグループ

SecurityGroup は、セキュリティーグループの ID を指定します。セキュリティーグループというのは、実際にはインスタンスではなく ENI にくっつくファイアウォール機能のことです。ENI を特別指定しないと自動で ENI が作られて eth0 としてインスタンスに割り当てられるのですが、その ENI のセキュリティーグループを指定します。セキュリティーグループはステートフルで、許可を追加していきます。つまり、許可が無ければ拒否です。「10.0.3.0/24 からの TCP 22 ポートへのアクセスは通す」や「8.8.8.8 への UDP 53 ポートへのアクセスは通す」のような設定が可能です。

サブネット

SubnetId は、インスタンス作成時に自動作成される ENI の所属するサブネットを指定します。VPC を作成するときに CIDR で IP アドレスの範囲を指定するのですが、更にサブネットに分けて用途に応じたインスタンスの配置が可能です。VPC 内にサブネットを作成するときには AZ を指定する必要があります。

さて、これで AMI の情報を元に指定したインスタスタイプのインスタンスがとあるサブネット内に作成されて、セキュリティーグループで許可された IP アドレスから RSA 秘密鍵を使って接続できそうなのですが、接続のことを考えるのにもう少しサブネットとその周りのことを。

VPC のサブネット

サブネットは VPC のアドレス範囲内の更に小さなまとまりでしたが、各サブネットには仮想ゲートウェイが存在しており DHCPデフォルトゲートウェイとして提供されます。このゲートウェイは ネットワーク ACL とルートテーブルという属性を持っています。

ネットワーク ACL

ネットワーク ACL はサブネットに対するファイアウォールです。これはステートレスで、ルールとして許可も拒否も書けます。

ルートテーブル

ルートテーブルは、CIDR などで指定された IP パケットの行き先に対して、次のルーティングは誰にするかを指定するもので、基本的なルーティング先は以下の三つ。

ローカルはデフォルトで設定されていて外すことはできません。つまり、ルーティング的には VPC 内のパケットは必ず宛先サブネットまでは転送されてしまいます。遮断の為にはセキュリティーグループやネットワーク ACL の設定が必要です。

インターネットゲートウェイは、VPC とインターネットに接続されていてスタティック NAT をしてくれる仮想的なゲートウェイです。VPC 内のアドレスは通常はプライベートネットワークなので、そのままではインターネットには出られません。ENI に割りふられた IP address にグローバル IP アドレスを紐付けることができ、インターネットゲートウェイは紐付けに基いて NAT をしてくれます。グローバル IP アドレスの紐付けは、サブネットによって自動で行われる場合と、EIP (Elastic IP address) を借りて手動で割り当てる方法の 2 つがあります。

ENI を指定した場合には ENI の付いているインスタンスが一旦そのパケットを受け何らかの処理をします。例えば、外部からの接続を受けたくない場合、インターネットゲートウェイの設定のないサブネットを作ります。ただ、このままだとインターネットに出ていくこともできず不便です。そこで、ENI を転送先に指定することにより、別サブネットのインスタンスへパケットを転送し、そのインスタンスがダイナミック NAT してインターネットゲートウェイに転送することができます (NAT インスタンス)。でも、最近は NAT ゲートウェイというマネージド NAT インスタンスが出たので、そちらを使う方が主流になっているかも...。

他には下記の転送先があります

というわけで

インターネットからインスタンスまでの概念上の登場人物を列挙してみました。VPC は Virtual って頭に付いてるだけあって実体は外にあって、というのが私のイメージで、EC2 っていうといつも下のような絵を思いうかべています。レイヤーがゴチャっとなっている中々いびつな絵なんですけれどもね...。