1
1

More than 3 years have passed since last update.

Rubyでprophetを使う

Last updated at Posted at 2021-02-22

自分で使うにあたって、頭の整理も兼ねて記事にしました。

rubyで時系列予測がしたい!

  • 全部rubyでやりたい
  • railsで動かしてるシステムの中で予測値を出したい
  • pythonやRなどでいいライブラリはいっぱいあるが、railsとのつなぎこみが面倒臭い
  • スプレッドシートのTREND関数などもあるけど、やっぱりrailsとのつなぎこみが面倒臭い
  • 全部rubyでやりたい

prophetを使おう

prophet-rbというgemを使います。
https://github.com/ankane/prophet

元はfacebook/prophet(https://github.com/facebook/prophet )。これを移植してきたもの。

  • 複数の季節性
  • 線形/非線形成長
  • 祝日など特別な日のハンドリング
  • 欠損値処理 などをいい感じにやってくれる。

インストール

Gemfileに以下の行を追記。

gem 'prophet-rb'

まずは試しに

{ 時系列: 実績値 }のハッシュを用意します。

series = {
  Date.parse("2020-01-01") => 100,
  Date.parse("2020-01-02") => 150,
  Date.parse("2020-01-03") => 136,
  Date.parse("2020-01-04") => 130,
  Date.parse("2020-01-05") => 128,
  Date.parse("2020-01-06") => 120,
  Date.parse("2020-01-07") => 135,
  Date.parse("2020-01-08") => 136,
  Date.parse("2020-01-09") => 127,
  Date.parse("2020-01-10") => 138
}
Prophet.forecast(series, count: 3) # 二つ目の引数で予測値をいくつ返すか指定

これを実行すると、下のように予測値が得られる、というわけです。予測に使う元データは最低10個必要です。

> Prophet.forecast(series, count: 3)
=> {Sat, 11 Jan 2020=>136.19586588066147, Sun, 12 Jan 2020=>137.322312420595, Mon, 13 Jan 2020=>138.44875896052858}

CSVを読み込んで時系列予測をする

df = Rover.read_csv("example_wp_log_peyton_manning.csv")
df.head

こういうcsvがあったとする。

ds y
2007-12-10 9.59076113
2007-12-11 8.51959031
2007-12-12 8.18367658
2007-12-13 8.07246736
2007-12-14 7.89357207
m = Prophet.new
m.fit(df)

fitメソッドで予測。

将来の時系列を与えて予測してみる

future = m.make_future_dataframe(periods: 365)
future.tail
ds
2007-12-10
2007-12-11
2007-12-12
2007-12-13
2007-12-14
forecast = m.predict(future)
forecast[["ds", "yhat", "yhat_lower", "yhat_upper"]].tail
ds yhat yhat_lower yhat_upper
2017-01-15 8.21192840 7.52526442 8.92389960
2017-01-16 8.53696359 7.79124970 9.22620028
2017-01-17 8.32439891 7.62482699 9.04719328

下限/上限まで出してくれる!すごい!
https://github.com/mrkn/matplotlib.rb
これも使うといい感じに可視化までしてくれます。

Saturating Forecasts

詳しい説明はこちら
https://facebook.github.io/prophet/docs/saturating_forecasts.html

df = Rover.read_csv("example_wp_log_R.csv")
df["cap"] = 8.5
m = Prophet.new(growth: "logistic")
m.fit(df)
future = m.make_future_dataframe(periods: 365)
future["cap"] = 8.5
forecast = m.predict(future)

トレンドがのchange points

fig = m.plot(forecast)
m.add_changepoints_to_plot(fig.gca, forecast)

特別な日の設定

holiday列とds列を持つデータフレームを作成します。過去のデータに含まれるすべての事象と、予測したい将来の事象を含めます。

playoffs = Rover::DataFrame.new(
  "holiday" => "playoff",
  "ds" => ["2008-01-13", "2009-01-03", "2010-01-16",
           "2010-01-24", "2010-02-07", "2011-01-08",
           "2013-01-12", "2014-01-12", "2014-01-19",
           "2014-02-02", "2015-01-11", "2016-01-17",
           "2016-01-24", "2016-02-07"],
  "lower_window" => 0,
  "upper_window" => 1
)

superbowls = Rover::DataFrame.new(
  "holiday" => "superbowl",
  "ds" => ["2010-02-07", "2014-02-02", "2016-02-07"],
  "lower_window" => 0,
  "upper_window" => 1
)
holidays = playoffs.concat(superbowls)

m = Prophet.new(holidays: holidays)
m.fit(df)

国別の祝日を入れることもできる

m = Prophet.new
m.add_country_holidays(country_name: "US")
m.fit(df)

季節性も設定できる。

m = Prophet.new(weekly_seasonality: false)
m.add_seasonality(name: "monthly", period: 30.5, fourier_order: 5)
forecast = m.fit(df).predict(future)

他にも色々な機能があります!本当に便利ですね。。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1