Rを使用した時系列分析の手順と方法


13

私は、今後6か月間、商品(石油、アルミニウム、錫など)の価格を予測しようとする小さなプロジェクトに取り組んでいます。予測するそのような変数は12個あり、2008年4月から2013年5月までのデータがあります。

予測についてはどうすればいいですか?私は次のことをしました:

  • Timeseriesデータセットとしてインポートされたデータ
  • すべての変数の季節性はトレンドによって異なる傾向があるため、乗法モデルを使用します。
  • 加算モデルに変換する変数のログを取りました
  • 各変数について、STLを使用してデータを分解しました

Holt Winters指数平滑法、ARIMAおよびニューラルネットを使用して予測する予定です。トレーニングとテストとしてデータを分割しました(80、20)。MAE、MPE、MAPE、MASEの少ないモデルを選択する計画。

私はそれを正しくやっていますか?

また、ARIMAまたはニューラルネットに渡す前に、データを平滑化する必要がありましたか?はいの場合、何を使用しますか?データは、季節性と傾向の両方を示しています。

編集:

時系列のプロットとデータの添付 ここに画像の説明を入力してください

Year  <- c(2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2009, 2009, 
           2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2009, 2010, 
           2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 2010, 
           2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 
           2011, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 
           2012, 2012, 2013, 2013)
Month <- c(4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
           12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 
           8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2) 
Coil  <- c(44000, 44500, 42000, 45000, 42500, 41000, 39000, 35000, 34000, 
           29700, 29700, 29000, 30000, 30000, 31000, 31000, 33500, 33500, 
           33000, 31500, 34000, 35000, 35000, 36000, 38500, 38500, 35500, 
           33500, 34500, 36000, 35500, 34500, 35500, 38500, 44500, 40700, 
           40500, 39100, 39100, 39100, 38600, 39500, 39500, 38500, 39500, 
           40000, 40000, 40500, 41000, 41000, 41000, 40500, 40000, 39300, 
           39300, 39300, 39300, 39300, 39800)
coil <- data.frame(Year = Year, Month = Month, Coil = Coil)

編集2: 1つの質問、私のデータに季節や傾向があるかどうか教えてください。また、それらを識別する方法に関するヒントをいくつか教えてください。 ここに画像の説明を入力してください ここに画像の説明を入力してください


2
さまざまな種類の金属(スチールA、スチールB、スチールCなど)などの商品グループを予測しようとしている場合、共和分が存在するかどうかをテストする価値があります。たとえば、次のようなものです:鉄鋼価格は一緒に動きますか?。これは、単変量法よりも優れた6か月(中/長期)予測を提供する可能性がありますが、実際、これはプレイしようとしている難しいゲームです。;-)
グレームウォルシュ

1
@GraemeWalshが指摘しているように、単変量トレンドの外挿はこのタイプのデータには理想的ではないかもしれません。文献には、石油、鉄鋼の価格を予測するための十分に確立された方法があり、調査する価値があります。
予報官

1
新しい編集を別の質問として投稿できますか?すでに回答を受け入れているため、新しい質問では必要な注意が集まらない場合があります。データを目で見てみると、トレンドや季節パターンのあるものはないと言えます。以下の私の投稿で述べたように、2009年以前の下降傾向は不況のようなマクロ経済現象のように見えますか?
予報官

@ forecaster、@ GraemeWalsh:ありがとう。ADFテストを使用した共和分法を使用する予定です。
ニランジャンソナチャラム

1
あなたは新しい質問に文脈を提供しました、そしてそれは今やモスセンスになります。したがって、2009年以前に低下したのは、確かにいくつかのマクロ経済現象でした。その場合は、ドリフトまたは(arima(0,1,0)+ drift-
予測者

回答:


21

これらのモデル(およびそれ以上)をすべてサポートし、それらを簡単に適合させる予測パッケージを使用する必要があります。

library(forecast)
x <- AirPassengers
mod_arima <- auto.arima(x, ic='aicc', stepwise=FALSE)
mod_exponential <- ets(x, ic='aicc', restrict=FALSE)
mod_neural <- nnetar(x, p=12, size=25)
mod_tbats <- tbats(x, ic='aicc', seasonal.periods=12)
par(mfrow=c(4, 1))
plot(forecast(mod_arima, 12), include=36)
plot(forecast(mod_exponential, 12), include=36)
plot(forecast(mod_neural, 12), include=36)
plot(forecast(mod_tbats, 12), include=36)

モデルを近似する前にデータを平滑化することはお勧めしません。モデルは本質的にデータを平滑化しようとするため、事前平滑化は物事を複雑にします。

ここに画像の説明を入力してください

新しいデータに基づいて編集:

実際、arimaは、このトレーニングおよびテストセットで選択できる最悪のモデルの1つであるように見えます。

データをファイル呼び出しに保存し、coil.csvRにロードして、トレーニングとテストセットに分割しました。

library(forecast)
dat <- read.csv('~/coil.csv')
x <- ts(dat$Coil, start=c(dat$Year[1], dat$Month[1]), frequency=12)
test_x <- window(x, start=c(2012, 3))
x <- window(x, end=c(2012, 2))

次に、一連の時系列モデルを適合させます:arima、指数平滑法、ニューラルネットワーク、tbat、bats、季節分解、および構造時系列:

models <- list(
  mod_arima = auto.arima(x, ic='aicc', stepwise=FALSE),
  mod_exp = ets(x, ic='aicc', restrict=FALSE),
  mod_neural = nnetar(x, p=12, size=25),
  mod_tbats = tbats(x, ic='aicc', seasonal.periods=12),
  mod_bats = bats(x, ic='aicc', seasonal.periods=12),
  mod_stl = stlm(x, s.window=12, ic='aicc', robust=TRUE, method='ets'),
  mod_sts = StructTS(x)
  )

次に、いくつかの予測を行い、テストセットと比較しました。常に水平な水平線を予測する単純な予測を含めました。

forecasts <- lapply(models, forecast, 12)
forecasts$naive <- naive(x, 12)
par(mfrow=c(4, 2))
for(f in forecasts){
  plot(f)
  lines(test_x, col='red')
}

ここに画像の説明を入力してください

ご覧のとおり、arimaモデルはトレンドを間違えていますが、「Basic Structural Model」の外観が好きです

最後に、テストセットで各モデルの精度を測定しました。

acc <- lapply(forecasts, function(f){
  accuracy(f, test_x)[2,,drop=FALSE]
})
acc <- Reduce(rbind, acc)
row.names(acc) <- names(forecasts)
acc <- acc[order(acc[,'MASE']),]
round(acc, 2)
                ME    RMSE     MAE   MPE MAPE MASE ACF1 Theil's U
mod_sts     283.15  609.04  514.46  0.69 1.27 0.10 0.77      1.65
mod_bats     65.36  706.93  638.31  0.13 1.59 0.12 0.85      1.96
mod_tbats    65.22  706.92  638.32  0.13 1.59 0.12 0.85      1.96
mod_exp      25.00  706.52  641.67  0.03 1.60 0.12 0.85      1.96
naive        25.00  706.52  641.67  0.03 1.60 0.12 0.85      1.96
mod_neural   81.14  853.86  754.61  0.18 1.89 0.14 0.14      2.39
mod_arima   766.51  904.06  766.51  1.90 1.90 0.14 0.73      2.48
mod_stl    -208.74 1166.84 1005.81 -0.52 2.50 0.19 0.32      3.02

使用されるメトリックは、Hyndman、RJおよびAthanasopoulos、G.(2014)「予測:原則と実践」で説明されています。これらは、予測パッケージの作成者でもあります。テキストを読むことを強くお勧めします。オンラインで無料で入手できます。構造的時系列は、MASEを含むいくつかのメトリックによる最適なモデルです。MASEは、モデルの選択に好まれるメトリックです。

最後の質問の1つは、このテストセットで構造モデルが幸運になったかどうかです。これを評価する1つの方法は、トレーニングセットのエラーを見ることです。トレーニングセットのエラーは、テストセットのエラーよりも信頼性が低くなります(これらは過適合になる可能性があるため)が、この場合、構造モデルが引き続き上位に表示されます。

acc <- lapply(forecasts, function(f){
  accuracy(f, test_x)[1,,drop=FALSE]
})
acc <- Reduce(rbind, acc)
row.names(acc) <- names(forecasts)
acc <- acc[order(acc[,'MASE']),]
round(acc, 2)
                ME    RMSE     MAE   MPE MAPE MASE  ACF1 Theil's U
mod_sts      -0.03    0.99    0.71  0.00 0.00 0.00  0.08        NA
mod_neural    3.00 1145.91  839.15 -0.09 2.25 0.16  0.00        NA
mod_exp     -82.74 1915.75 1359.87 -0.33 3.68 0.25  0.06        NA
naive       -86.96 1936.38 1386.96 -0.34 3.75 0.26  0.06        NA
mod_arima  -180.32 1889.56 1393.94 -0.74 3.79 0.26  0.09        NA
mod_stl     -38.12 2158.25 1471.63 -0.22 4.00 0.28 -0.09        NA
mod_bats     57.07 2184.16 1525.28  0.00 4.07 0.29 -0.03        NA
mod_tbats    62.30 2203.54 1531.48  0.01 4.08 0.29 -0.03        NA

(ニューラルネットワークのオーバーフィットは、トレーニングセットで優れたパフォーマンスを発揮し、テストセットでは不十分なことに注意してください)

最後に、おそらく2008-2009 / 2010年のテスト、2008-2010 / 2011年のテスト、2008-2011 / 2012年のテスト、トレーニングのトレーニングによって、これらすべてのモデルを相互検証することをお勧めします。 2008-2012 / 2013のテスト、およびこれらの期間全体のエラーの平均化。そのルートを下る場合は、GitHub時系列モデルを相互検証するための部分的に完全なパッケージがあります。試してみて、フィードバック/プルリクエストをお願いします。

devtools::install_github('zachmayer/cv.ts')
library(cv.ts)

編集2:自分のパッケージの使用方法を覚えているかどうかを確認しましょう!

まず、githubからパッケージをインストールしてロードします(上記を参照)。次に、いくつかのモデルを相互検証します(完全なデータセットを使用):

library(cv.ts)
x <- ts(dat$Coil, start=c(dat$Year[1], dat$Month[1]), frequency=12)
ctrl <- tseriesControl(stepSize=1, maxHorizon=12, minObs=36, fixedWindow=TRUE)
models <- list()

models$arima = cv.ts(
  x, auto.arimaForecast, tsControl=ctrl,
  ic='aicc', stepwise=FALSE)

models$exp = cv.ts(
  x, etsForecast, tsControl=ctrl,
  ic='aicc', restrict=FALSE)

models$neural = cv.ts(
  x, nnetarForecast, tsControl=ctrl,
  nn_p=6, size=5)

models$tbats = cv.ts(
  x, tbatsForecast, tsControl=ctrl,
  seasonal.periods=12)

models$bats = cv.ts(
  x, batsForecast, tsControl=ctrl,
  seasonal.periods=12)

models$stl = cv.ts(
  x, stl.Forecast, tsControl=ctrl,
  s.window=12, ic='aicc', robust=TRUE, method='ets')

models$sts = cv.ts(x, stsForecast, tsControl=ctrl)

models$naive = cv.ts(x, naiveForecast, tsControl=ctrl)

models$theta = cv.ts(x, thetaForecast, tsControl=ctrl)

(ニューラルネットワークモデルの柔軟性を低下させて、過剰適合を防止することに注意してください)

モデルを適合させたら、MAPEでそれらを比較できます(cv.tsはまだMASEをサポートしていません):

res_overall <- lapply(models, function(x) x$results[13,-1])
res_overall <- Reduce(rbind, res_overall)
row.names(res_overall) <- names(models)
res_overall <- res_overall[order(res_overall[,'MAPE']),]
round(res_overall, 2)
                 ME    RMSE     MAE   MPE MAPE
naive     91.40 1126.83  961.18  0.19 2.40
ets       91.56 1127.09  961.35  0.19 2.40
stl     -114.59 1661.73 1332.73 -0.29 3.36
neural     5.26 1979.83 1521.83  0.00 3.83
bats     294.01 2087.99 1725.14  0.70 4.32
sts     -698.90 3680.71 1901.78 -1.81 4.77
arima  -1687.27 2750.49 2199.53 -4.23 5.53
tbats   -476.67 2761.44 2428.34 -1.23 6.10

痛い。構造的な予測は運がよかったようです。長期にわたって、素朴な予測は、12か月の期間にわたって平均された最良の予測を作成します(アリマモデルは依然として最悪のモデルの1つです)。12の予測期間のそれぞれでモデルを比較し、それらのいずれかが単純なモデルに勝ったかどうかを確認しましょう。

library(reshape2)
library(ggplot2)
res <- lapply(models, function(x) x$results$MAPE[1:12])
res <- data.frame(do.call(cbind, res))
res$horizon <- 1:nrow(res)
res <- melt(res, id.var='horizon', variable.name='model', value.name='MAPE')
res$model <- factor(res$model, levels=row.names(res_overall))
ggplot(res, aes(x=horizon, y=MAPE, col=model)) +
  geom_line(size=2) + theme_bw() +
  theme(legend.position="top") +
  scale_color_manual(values=c(
    "#1f78b4", "#ff7f00", "#33a02c", "#6a3d9a",
    "#e31a1c", "#b15928", "#a6cee3", "#fdbf6f",
    "#b2df8a")
    )

モデル比較

明らかに、指数平滑法モデルは常に単純なモデルを選択しています(オレンジ色の線と青い線は100%オーバーラップしています)。言い換えれば、「来月のコイル価格は今月のコイル価格と同じになる」という単純な予測は、7つの非常に洗練された時系列モデルよりも(ほぼすべての予測期間で)より正確です。コイル市場がまだ知らない秘密情報がない限り、単純なコイル価格予測を破ることは非常に困難です。

誰も聞きたくない答えではありませんが、予測精度が目標である場合は、最も正確なモデルを使用する必要があります。素朴なモデルを使用します。


これらのモデルの違いを見るのは面白いです。特にNNARは異なって見えます。これが有名なデータセット(および歴史的に古い、私は信じている)であることを考えると、どちらが正しいか、1つのモデルタイプが優れているかどうかはわかりますか?(Nb、私はTSについて比較的少ししか知りません。)
グング-モニカの復職

@gungこれを行う最良の方法は、ホールドアウトセットを分割してモデルをテストすることです。最高の短期的な予測を行い、モデルが最良の長期的な見通しを作るモデルではないかもしれないことに注意してください....
ザック

どうもありがとうございますが、上記のデータセットについては良い予測が得られていません(ここでいくつかの重要なステップを見逃していると思います)。何かが足りない場合はお知らせください
ニランハンソナチャラム

@Niranjan良い予報が得られないと結論付ける方法を教えてください。
予報官

@forecaster:こちらpbrd.co/1DRPRsqをチェックしてください。予測は初めてです。特定の情報が必要な場合はお知らせください。有馬モデルで試しました。
ニランジャンソナチャラム

12

あなたが取ったアプローチは合理的です。予測が初めての場合は、次の書籍をお勧めします。

  1. Makridakis、Wheelright、Hyndmanによる予測方法とアプリケーション
  2. 予測: HyndmanとAthanasopoulosによる原則と実践

最初の本は私が強くお勧めする古典です。2冊目の本は、予測方法と、Rオープンソースソフトウェアパッケージの予測を使用した予測方法について参照できるオープンソースの本です 。両方の本は、私が使用した方法の良い背景を提供します。予測を真剣に考えている場合は、Armstrongによる予測の原則をお勧めします。これは、実務家が非常に役立つと予測するための膨大な量の研究のコレクションです。

コイルの特定の例について説明すると、ほとんどの教科書でよく無視される予測可能性の概念を思い起こさせます。シリーズなどの一部のシリーズは、トレンドや季節的なパターン、または系統的な変動を示さないため、パターンが少ないため、単に予測できません。その場合、シリーズを予測不能として分類します。外挿法に進む前に、データを見て質問をするのですが、シリーズは予測可能ですか?この具体例では、予測の最後の値を使用するランダムウォーク予測などの単純な外挿が最も正確であることがわかりました。

また、ニューラルネットワークに関する1つの追加コメント:ニューラルネットワークは、経験的な競争で失敗することで有名です。時系列予測タスクにニューラルネットワークを使用する前に、時系列の従来の統計的手法を試してみました。

でデータをモデル化しようとしましたR's forecast packageが、コメントが自明であることを願っています。

coil <- c(44000, 44500, 42000, 45000, 42500, 41000, 39000, 35000, 34000, 
          29700, 29700, 29000, 30000, 30000, 31000, 31000, 33500, 33500, 
          33000, 31500, 34000, 35000, 35000, 36000, 38500, 38500, 35500, 
          33500, 34500, 36000, 35500, 34500, 35500, 38500, 44500, 40700, 
          40500, 39100, 39100, 39100, 38600, 39500, 39500, 38500, 39500, 
          40000, 40000, 40500, 41000, 41000, 41000, 40500, 40000, 39300, 
          39300, 39300, 39300, 39300, 39800)


coilts <- ts(coil,start=c(2008,4),frequency=12)

library("forecast")

# Data for modeling
coilts.mod <- window(coilts,end = c(2012,3))

#Data for testing
coil.test <- window(coilts,start=c(2012,4))

# Model using multiple methods - arima, expo smooth, theta, random walk, structural time series

#arima
coil.arima <- forecast(auto.arima(coilts.mod),h=11)

#exponential smoothing
coil.ets <- forecast(ets(coilts.mod),h=11)

#theta
coil.tht <- thetaf(coilts.mod, h=11)

#random walk
coil.rwf <- rwf(coilts.mod, h=11)

#structts
coil.struc <- forecast(StructTS(coilts.mod),h=11)


##accuracy 

arm.acc <- accuracy(coil.arima,coil.test)
ets.acc <- accuracy(coil.ets,coil.test)
tht.acc <- accuracy(coil.tht,coil.test)
rwf.acc <- accuracy(coil.rwf,coil.test)
str.acc <- accuracy(coil.struc,coil.test)

ホールドアウトデータでMAEを使用して、短期予測(1〜12か月)にARIMAを選択します。長期的には、ランダムウォーク予測に依存します。ARIMAはドリフト(0,1,0)+ドリフトのあるランダムウォークモデルを選択したことに注意してください。これらのタイプの問題は、特に短期的には純粋なランダムウォークモデルよりもはるかに正確になる傾向があります。下のチャートをご覧ください。これは、上記のコードに示されている精度関数に基づいています。

ここに画像の説明を入力してください

特定の質問に対する具体的な回答:また、ARIMAまたはニューラルネットに渡す前に、データを平滑化する必要がありましたか?はいの場合、何を使用しますか?

  • いいえ、予測方法はデータをモデルに合わせて自然に平滑化します。

データは、季節性と傾向の両方を示しています。

  • 上記のデータは、傾向や季節性を示していません。データが季節性と傾向を示すと判断した場合は、適切な方法を選択してください。

精度を向上させるための実用的なヒント:

さまざまな予測方法を組み合わせます。- 類推による予測、判断予測、またはその他の 手法などの非外挿法を使用して、統計手法と組み合わせて正確な予測を提供できます。組み合わせるメリットについては、この記事をご覧ください。上記の5つの方法を組み合わせてみましたが、予測は個々の方法として正確ではありませんでした。考えられる理由の1つは、個々の予測が類似していることです。統計的予測や判断的予測などのさまざまな方法を組み合わせると、予測を組み合わせる利点を享受できます。

外れ値の検出と理解: -現実世界のデータは外れ値で満たされています。時系列で外れ値を特定し、適切に処理します。この投稿を読むことをお勧めします。コイルデータを見ると、2009年以前の低下は異常値ですか??

編集

データは、ある種のマクロ経済動向に従っているようです。私の推測では、2009年以前に見られた下降傾向は2008年から2009年の間に見られる経済の低迷に続き、2009年以降に持ち直し始めます。そうであれば、外挿法の使用を避け、代わりに健全な理論に依存しますこれらの経済動向は、@ GraemeWalshが参照するような動きをします。

お役に立てれば

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.