Vantage 時系列関数を利用した架空の航空会社の旅客数予測

# はじめに
ある架空の航空会社である**XYZ エアライン**の分析ユースケースを想定して話しを進めたいと思います。
新興企業である XYZ エアラインは 実績ベースの時系列データを元にして 航空会社を利用する乗客数の需要を予測したいと考えました。
**ARIMAモデル** は 信頼性も高く 効率的で 短期の株式市場の動きを予測する事でも認められており 多くの分野で予測に広く利用されている分析手法です。
そこで 航空機の需要(搭乗者数)を予測するためにARIMAモデルを構築する事にしました。

:::note info
**ARIMA**(Auto Regressive Integrated Moving Average)は **AR**(Auto Regressive)と**MA**(Moving Average)の2つのモデルを組み合わせたモデルです。
それぞれ **AR**、**I**、**MA**の要素に由来しており **AR**の部分は前期と後期の相関、**MA**はノイズを平滑化するためのもの。**I** は **AR** と **MA** を結合します。
ハイパーパラメータとして **P**(自己回帰ラグ)、**D**(微分次数)、**Q**(移動平均)の要素を持ちます。
:::

# 1. データセットを用意する
## 1.1. airpassengersテーブルを作成
デモで使用するデータは Vantage上に存在する事を前提とします。
データは 2007年から2018年までの月別フライト実績(144行)です。
この分析手法は 複数の時系列を同時に持つ巨大なデータセットにも適用することが可能です。

```sql:airpassengersテーブル
CREATE MULTISET TABLE airpassengers
(
      "Date" TIMESTAMP(6),                          -- 搭乗日
      Passengers BIGINT,                            -- 搭乗者数
      seriesID VARCHAR(1024) CHARACTER SET UNICODE  -- 系列
)
PRIMARY INDEX
(
	"Date"
);
```

<details><summary>サンプルデータ</summary>

```:airpassengers.csv
"Date","Passengers","seriesID"
"2007-01-01 01:33:36.000000","112","FlyHigh"
"2007-02-01 01:33:36.000000","118","FlyHigh"
"2007-03-01 01:33:36.000000","132","FlyHigh"
"2007-04-01 01:33:36.000000","129","FlyHigh"
"2007-05-01 01:33:36.000000","121","FlyHigh"
"2007-06-01 01:33:36.000000","135","FlyHigh"
"2007-07-01 01:33:36.000000","148","FlyHigh"
"2007-08-01 01:33:36.000000","148","FlyHigh"
"2007-09-01 01:33:36.000000","136","FlyHigh"
"2007-10-01 01:33:36.000000","119","FlyHigh"
"2007-11-01 01:33:36.000000","104","FlyHigh"
"2007-12-01 01:33:36.000000","118","FlyHigh"
"2008-01-01 01:33:36.000000","115","FlyHigh"
"2008-02-01 01:33:36.000000","126","FlyHigh"
"2008-02-29 01:33:36.000000","141","FlyHigh"
"2008-03-31 01:33:36.000000","135","FlyHigh"
"2008-04-30 01:33:36.000000","125","FlyHigh"
"2008-05-31 01:33:36.000000","149","FlyHigh"
"2008-06-30 01:33:36.000000","170","FlyHigh"
"2008-07-31 01:33:36.000000","170","FlyHigh"
"2008-08-31 01:33:36.000000","158","FlyHigh"
"2008-09-30 01:33:36.000000","133","FlyHigh"
"2008-10-31 01:33:36.000000","114","FlyHigh"
"2008-11-30 01:33:36.000000","140","FlyHigh"
"2008-12-31 01:33:36.000000","145","FlyHigh"
"2009-01-31 01:33:36.000000","150","FlyHigh"
"2009-02-28 01:33:36.000000","178","FlyHigh"
"2009-03-31 01:33:36.000000","163","FlyHigh"
"2009-04-30 01:33:36.000000","172","FlyHigh"
"2009-05-31 01:33:36.000000","178","FlyHigh"
"2009-06-30 01:33:36.000000","199","FlyHigh"
"2009-07-31 01:33:36.000000","199","FlyHigh"
"2009-08-31 01:33:36.000000","184","FlyHigh"
"2009-09-30 01:33:36.000000","162","FlyHigh"
"2009-10-31 01:33:36.000000","146","FlyHigh"
"2009-11-30 01:33:36.000000","166","FlyHigh"
"2009-12-31 01:33:36.000000","171","FlyHigh"
"2010-01-31 01:33:36.000000","180","FlyHigh"
"2010-03-01 01:33:36.000000","193","FlyHigh"
"2010-04-01 01:33:36.000000","181","FlyHigh"
"2010-05-01 01:33:36.000000","183","FlyHigh"
"2010-06-01 01:33:36.000000","218","FlyHigh"
"2010-07-01 01:33:36.000000","230","FlyHigh"
"2010-08-01 01:33:36.000000","242","FlyHigh"
"2010-09-01 01:33:36.000000","209","FlyHigh"
"2010-10-01 01:33:36.000000","191","FlyHigh"
"2010-11-01 01:33:36.000000","172","FlyHigh"
"2010-12-01 01:33:36.000000","194","FlyHigh"
"2011-01-01 01:33:36.000000","196","FlyHigh"
"2011-02-01 01:33:36.000000","196","FlyHigh"
"2011-03-01 01:33:36.000000","236","FlyHigh"
"2011-04-01 01:33:36.000000","235","FlyHigh"
"2011-05-01 01:33:36.000000","229","FlyHigh"
"2011-06-01 01:33:36.000000","243","FlyHigh"
"2011-07-01 01:33:36.000000","264","FlyHigh"
"2011-08-01 01:33:36.000000","272","FlyHigh"
"2011-09-01 01:33:36.000000","237","FlyHigh"
"2011-10-01 01:33:36.000000","211","FlyHigh"
"2011-11-01 01:33:36.000000","180","FlyHigh"
"2011-12-01 01:33:36.000000","201","FlyHigh"
"2012-01-01 01:33:36.000000","204","FlyHigh"
"2012-02-01 01:33:36.000000","188","FlyHigh"
"2012-02-29 01:33:36.000000","235","FlyHigh"
"2012-03-31 01:33:36.000000","227","FlyHigh"
"2012-04-30 01:33:36.000000","234","FlyHigh"
"2012-05-31 01:33:36.000000","264","FlyHigh"
"2012-06-30 01:33:36.000000","302","FlyHigh"
"2012-07-31 01:33:36.000000","293","FlyHigh"
"2012-08-31 01:33:36.000000","259","FlyHigh"
"2012-09-30 01:33:36.000000","229","FlyHigh"
"2012-10-31 01:33:36.000000","203","FlyHigh"
"2012-11-30 01:33:36.000000","229","FlyHigh"
"2012-12-31 01:33:36.000000","242","FlyHigh"
"2013-01-31 01:33:36.000000","233","FlyHigh"
"2013-02-28 01:33:36.000000","267","FlyHigh"
"2013-03-31 01:33:36.000000","269","FlyHigh"
"2013-04-30 01:33:36.000000","270","FlyHigh"
"2013-05-31 01:33:36.000000","315","FlyHigh"
"2013-06-30 01:33:36.000000","364","FlyHigh"
"2013-07-31 01:33:36.000000","347","FlyHigh"
"2013-08-31 01:33:36.000000","312","FlyHigh"
"2013-09-30 01:33:36.000000","274","FlyHigh"
"2013-10-31 01:33:36.000000","237","FlyHigh"
"2013-11-30 01:33:36.000000","278","FlyHigh"
"2013-12-31 01:33:36.000000","284","FlyHigh"
"2014-01-31 01:33:36.000000","277","FlyHigh"
"2014-03-01 01:33:36.000000","317","FlyHigh"
"2014-04-01 01:33:36.000000","313","FlyHigh"
"2014-05-01 01:33:36.000000","318","FlyHigh"
"2014-06-01 01:33:36.000000","374","FlyHigh"
"2014-07-01 01:33:36.000000","413","FlyHigh"
"2014-08-01 01:33:36.000000","405","FlyHigh"
"2014-09-01 01:33:36.000000","355","FlyHigh"
"2014-10-01 01:33:36.000000","306","FlyHigh"
"2014-11-01 01:33:36.000000","271","FlyHigh"
"2014-12-01 01:33:36.000000","306","FlyHigh"
"2015-01-01 01:33:36.000000","315","FlyHigh"
"2015-02-01 01:33:36.000000","301","FlyHigh"
"2015-03-01 01:33:36.000000","356","FlyHigh"
"2015-04-01 01:33:36.000000","348","FlyHigh"
"2015-05-01 01:33:36.000000","355","FlyHigh"
"2015-06-01 01:33:36.000000","422","FlyHigh"
"2015-07-01 01:33:36.000000","465","FlyHigh"
"2015-08-01 01:33:36.000000","467","FlyHigh"
"2015-09-01 01:33:36.000000","404","FlyHigh"
"2015-10-01 01:33:36.000000","347","FlyHigh"
"2015-11-01 01:33:36.000000","305","FlyHigh"
"2015-12-01 01:33:36.000000","336","FlyHigh"
"2016-01-01 01:33:36.000000","340","FlyHigh"
"2016-02-01 01:33:36.000000","318","FlyHigh"
"2016-02-29 01:33:36.000000","362","FlyHigh"
"2016-03-31 01:33:36.000000","348","FlyHigh"
"2016-04-30 01:33:36.000000","363","FlyHigh"
"2016-05-31 01:33:36.000000","435","FlyHigh"
"2016-06-30 01:33:36.000000","491","FlyHigh"
"2016-07-31 01:33:36.000000","505","FlyHigh"
"2016-08-31 01:33:36.000000","404","FlyHigh"
"2016-09-30 01:33:36.000000","359","FlyHigh"
"2016-10-31 01:33:36.000000","310","FlyHigh"
"2016-11-30 01:33:36.000000","337","FlyHigh"
"2016-12-31 01:33:36.000000","360","FlyHigh"
"2017-01-31 01:33:36.000000","342","FlyHigh"
"2017-02-28 01:33:36.000000","406","FlyHigh"
"2017-03-31 01:33:36.000000","396","FlyHigh"
"2017-04-30 01:33:36.000000","420","FlyHigh"
"2017-05-31 01:33:36.000000","472","FlyHigh"
"2017-06-30 01:33:36.000000","548","FlyHigh"
"2017-07-31 01:33:36.000000","559","FlyHigh"
"2017-08-31 01:33:36.000000","463","FlyHigh"
"2017-09-30 01:33:36.000000","407","FlyHigh"
"2017-10-31 01:33:36.000000","362","FlyHigh"
"2017-11-30 01:33:36.000000","405","FlyHigh"
"2017-12-31 01:33:36.000000","417","FlyHigh"
"2018-01-31 01:33:36.000000","391","FlyHigh"
"2018-03-01 01:33:36.000000","419","FlyHigh"
"2018-04-01 01:33:36.000000","461","FlyHigh"
"2018-05-01 01:33:36.000000","472","FlyHigh"
"2018-06-01 01:33:36.000000","535","FlyHigh"
"2018-07-01 01:33:36.000000","622","FlyHigh"
"2018-08-01 01:33:36.000000","606","FlyHigh"
"2018-09-01 01:33:36.000000","508","FlyHigh"
"2018-10-01 01:33:36.000000","461","FlyHigh"
"2018-11-01 01:33:36.000000","390","FlyHigh"
"2018-12-01 01:33:36.000000","432","FlyHigh"
```
</details>

## 1.2. データセットの内容を確認する
TD_PLOT関数は テーブルの内容からグラフを作成しイメージデータを返します。
次のクエリは **[TD_PLOT](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/Teradata-VantageTM-Unbounded-Array-Framework%E6%99%82%E7%B3%BB%E5%88%97%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-17.20/%E6%B1%8E%E7%94%A8%E3%83%A6%E3%83%BC%E3%83%86%E3%82%A3%E3%83%AA%E3%83%86%E3%82%A3%E9%96%A2%E6%95%B0/TD_PLOT)** を利用してグラフを生成します。
```SQL
EXECUTE FUNCTION
TD_Plot
(
    SERIES_SPEC
    (
        TABLE_NAME(DEMO_AirPassengers.airpassengers),
        ROW_AXIS(TIMECODE("Date")),
        SERIES_ID(seriesID),
        PAYLOAD (FIELDS("Passengers"),CONTENT(REAL))
    ),
    FUNC_PARAMS
    (
        PLOTS[(
            TYPE('line'),
            LEGEND('upper left'),
            TITLE('Number of Passengers Travelling Monthly')
        )],
        IMAGE('png')
    )
);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778293/018ba5e3-c757-c5bc-46c5-1e20dd68ec96.png)

# 2. ARIMAモデルを利用した将来の航空機の搭乗者数を予測する
## 2.1. 検定ステップ

### 2.1.(1). ディッキー・フラー検定で定常性を検定する
ディッキー・フラー検定は 時系列データの平均と分散が異なる期間にわたって一定であるかどうかを判断するために広く使用されています。

時系列データに統計モデルを適用する前に 始めにデータが一定である事を確認する必要があります。
a) 時系列データは一定の平均値を持つ必要があります。
b) 時系列データは一定の分散または標準偏差を持つ必要があります。
c) 自己共分散は時間に依存してはなりません。

次のクエリは **[TD_DICKEY_FULLER](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/Teradata-VantageTM-Unbounded-Array-Framework%E6%99%82%E7%B3%BB%E5%88%97%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-17.20/%E8%A8%BA%E6%96%AD%E7%9A%84%E7%B5%B1%E8%A8%88%E6%A4%9C%E5%AE%9A%E9%96%A2%E6%95%B0/TD_DICKEY_FULLER)** を使用して **定常性をチェック** しています。

```SQL:TD_DICKEY_FULLER関数
EXECUTE FUNCTION
TD_DICKEY_FULLER(
    SERIES_SPEC(
        TABLE_NAME(DEMO_AirPassengers.airpassengers),
        ROW_AXIS(TIMECODE("Date")),
        SERIES_ID("seriesID"),
        PAYLOAD(
            FIELDS("Passengers"),
            CONTENT(REAL)
        )
    ),
    FUNC_PARAMS(
        ALGORITHM('TREND')
    )
);
```
|seriesID|ROW_I|NUM_SAMPLES|ALGORITHM|T_STAT|P_VALUE|NULL_HYP|
|:-|:-|:-|:-|:-|:-|:-|
|FlyHigh|0|144|TREND|-4.639196964346928|0.0008857695636920808|REJECT|

- **ACCEPT**は 帰無仮説が受け入れられたこと(結果は同じである)を意味します。
単位根(平均や分散が時間とともに変化する)が無く **定常的**です。
- **REJECT**は 帰無仮説が棄却されたこと(結果は同じでない)を意味します。
単位根(平均や分散が時間とともに変化する)があり **非定常的**です。
- NULL_HYP列を見ると時系列は非定常と言えます。

### 2.1.(2). TD_DIFFで時系列を定常化する(d)
TD_DIFFは 定常、非定常、季節性 の時系列データを差分化した時系列に変換します。
変換されたデータは指定されたテーブルに出力されます。
ここでは データの周期性を考慮して パラメータであるラグは 12(12ヵ月)に設定します。
次のクエリは 時系列を **[TD_DIFF](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/Teradata-VantageTM-Unbounded-Array-Framework%E6%99%82%E7%B3%BB%E5%88%97%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-17.20/%E3%83%A2%E3%83%86%E3%83%AB%E6%BA%96%E5%82%99%E9%96%A2%E6%95%B0%E3%81%8A%E3%82%88%E3%81%B2%E3%83%8F%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E6%8E%A8%E5%AE%9A%E9%96%A2%E6%95%B0/TD_DIFF)** を利用して差分時系列に変換します。
```SQL:TD_DIFF関数
EXECUTE FUNCTION
COLUMNS(OUT_Passengers AS Passengers)
INTO VOLATILE ART(diff1_air)
TD_DIFF(
    SERIES_SPEC(
            TABLE_NAME(DEMO_AirPassengers.airpassengers),
            ROW_AXIS(TIMECODE("Date")),
            SERIES_ID("seriesID"),
            PAYLOAD(
                FIELDS("Passengers"),
                CONTENT(REAL)
            )
    ),
    FUNC_PARAMS(
          LAG(12),
          DIFFERENCES(4),
          SEASONAL_MULTIPLIER(0)
    )
);
```

```SQL
SELECT TOP 5 * FROM diff1_air ORDER BY ROW_I;
```
|seriesID|ROW_I|Passengers|
|:-|:-|:-|
|FlyHigh|0|34|
|FlyHigh|1|-10|
|FlyHigh|2|100|
|FlyHigh|3|78|
|FlyHigh|4|150|

作成されたテーブルを **ディッキー・フラー検定** で定常であるかどうかをチェックします。時系列が定常化するまで TD_DIFF を再帰的に繰り返します。

```SQL:TD_DICKEY_FULLER関数
EXECUTE FUNCTION
TD_DICKEY_FULLER(
    SERIES_SPEC(
        TABLE_NAME(diff1_air),
        ROW_AXIS(SEQUENCE(ROW_I)),
        SERIES_ID("seriesID"),
        PAYLOAD(
            FIELDS("Passengers"),
            CONTENT(REAL)
        )
    ),
    FUNC_PARAMS(
        ALGORITHM('TREND')
    )
);
```
|seriesID|ROW_I|NUM_SAMPLES|ALGORITHM|T_STAT|P_VALUE|NULL_HYP|
|:-|:-|:-|:-|:-|:-|:-|
|FlyHigh|0|96|TREND|-3.1342412241637474|0.09831876940084541|ACCEPT|

NULL_HYP を見ると単位根(平均や分散が時間とともに変化する)は棄却され時系列は**定常である**ことがわかります。
この時系列を一次微分することで定常系列が得られます。したがって、微分次数の値は **D = 1** となり ARIMA_ESTIMATEでさらに使用されます。

### 2.1.(3). 時系列の自己相関を調べる(Q)
TD_ACFは時系列の自己相関または自己共分散を計算します。
自己相関と自己共分散は時系列が時間的または空間的な遅れによって遅延したときに それ自身とどのように相関または共分散するかを示します。
ここでは 最大12タイムステップのラグで自己相関を確認します。

次のクエリーは **[TD_ACF](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/Teradata-VantageTM-Unbounded-Array-Framework%E6%99%82%E7%B3%BB%E5%88%97%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-17.20/%E3%83%A2%E3%83%86%E3%83%AB%E6%BA%96%E5%82%99%E9%96%A2%E6%95%B0%E3%81%8A%E3%82%88%E3%81%B2%E3%83%8F%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E6%8E%A8%E5%AE%9A%E9%96%A2%E6%95%B0/TD_ACF/TD_ACF%E6%A7%8B%E6%96%87)** を使って自己共分散を計算します。
```SQL:TD_ACF関数
EXECUTE FUNCTION
COLUMNS(OUT_Passengers AS Auto_Correlation)
INTO VOLATILE ART(ACFDemo)
TD_ACF(
    SERIES_SPEC(
        TABLE_NAME(diff1_air),
        ROW_AXIS(SEQUENCE(ROW_I)),
        SERIES_ID("seriesID"),
        PAYLOAD(
            FIELDS("Passengers"),
            CONTENT(REAL)
        )
    ),
    FUNC_PARAMS(
        MAXLAGS(12),
        UNBIASED(0),    -- Use 0 for Jenkins-Watts formula, or 1 for BoxJenkins formula
        FUNC_TYPE(0),   -- Use 0 for autocorrelation, or 1 for autocovariance
        DEMEAN(1),
        QSTAT(0),
        ALPHA(0.05)
    )
);
```
```SQL
SELECT TOP 5 * FROM ACFDemo ORDER BY ROW_I;
```
|seriesID|ROW_I|Auto_Correlation|CONF_OFF_Passengers|CONF_LOW_Passengers|CONF_HI_Passengers|
|:-|:-|:-|:-|:-|:-|
|FlyHigh|0|1|0|1|1|
|FlyHigh|1|0.736849780698874|0.2000379865148046|0.5368117941840693|0.9368877672136786|
|FlyHigh|2|0.6092948162493547|0.2889074338100545|0.32038738243930015|0.8982022500594091|
|FlyHigh|3|0.41962593972958917|0.3364193839941808|0.08320655573540836|0.75604532372377|
|FlyHigh|4|0.3221378707614005|0.35674953103167856|-0.034611660270278066|0.678887401793079|

グラフで確認する。
```SQL:TD_Plot関数
EXECUTE FUNCTION
TD_Plot
(
    SERIES_SPEC
    (
        TABLE_NAME(ACFDemo),
        ROW_AXIS(SEQUENCE(ROW_I)),
        SERIES_ID(seriesID),
        PAYLOAD (FIELDS(Auto_Correlation, CONF_OFF_Passengers),CONTENT(MULTIVAR_REAL))
    ),
    FUNC_PARAMS
    (
        PLOTS[(
            TYPE('corr')
           ,LEGEND('best') 
        )],
        IMAGE('png')
    )
);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778293/488f49af-2c73-c44c-907c-911767d38a16.png)

移動平均 または Qの値を得るには ACFプロットからの値が有意限界のすぐ外側にあるラグ(ROW_Iの値)が必要です。
グラフを見ると ROW_I = 3における自己相関値は信頼帯の外側にあり信頼帯にかなり近い値です。
したがって **移動平均線 または Qの値 ＝ 3** とすることは許容範囲内です。

### 2.1.(4). 時系列の偏自己相関を調べる (P)
TD_PACF関数は モデル化された関数が定常的であるかどうかについて洞察します。
部分自己相関は 時系列サンプルポイント間の相関の程度を測定します。
ここでは 最大12タイムステップのラグで偏自己相関をチェックします。

```SQL:TD_PACF関数
EXECUTE FUNCTION
COLUMNS(OUT_Passengers AS Partial_Auto_Correlation)
INTO VOLATILE ART(PACFDemo)
TD_PACF (
    SERIES_SPEC(
        TABLE_NAME(diff1_air),
        ROW_AXIS(SEQUENCE(ROW_I)),
        SERIES_ID(seriesID),
        PAYLOAD(
            FIELDS("Passengers"),
            CONTENT(REAL)
        )
    ) ,
    FUNC_PARAMS(
        MAXLAGS(12),
        UNBIASED(0),    -- Use 0 for Jenkins-Watts formula, or 1 for BoxJenkins formula
        ALGORITHM(LEVINSON_DURBIN),
        ALPHA(0.05)
    )
);
```
```SQL
SELECT TOP 5 * FROM PACFDemo ORDER BY ROW_I;
```

|seriesID|ROW_I|Partial_Auto_Correlation|CONF_OFF_Passengers|CONF_LOW_Passengers|CONF_HI_Passengers|
|:-|:-|:-|:-|:-|:-|
|FlyHigh|0|1|0.2000379865148046|1|1|
|FlyHigh|1|0.736849780698874|0.2000379865148046|0.5368117941840693|0.9368877672136786|
|FlyHigh|2|0.145163261004824|0.2000379865148046|-0.0548747255099806|0.34520124751962855|
|FlyHigh|3|-0.1589643249713953|0.2000379865148046|-0.3590023114861999|0.0410736615434093|
|FlyHigh|4|0.036264086522446906|0.2000379865148046|-0.1637738999923577|0.23630207303725148|

グラフで確認します。
```SQL
EXECUTE FUNCTION
TD_Plot
(
    SERIES_SPEC
    (
        TABLE_NAME(PACFDemo),
        ROW_AXIS(SEQUENCE(ROW_I)),
        SERIES_ID(seriesID),
        PAYLOAD (FIELDS(Partial_Auto_Correlation, CONF_OFF_Passengers),CONTENT(MULTIVAR_REAL))
    ),
    FUNC_PARAMS
    (
        PLOTS[(
            TYPE('corr')
           ,LEGEND('best') 
        )],
        IMAGE('png')
    )
);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778293/a7d3a8e9-b3a5-c27f-46fb-0f5b600cbb07.png)

自己回帰ラグの値 つまり Pを求めるには PACFプロットからの値が有意限界のすぐ外に落ちるラグ(Row_Iの値)が必要です。
グラフを見るとROW_I = 1の部分自己相関の値は 有意水準から外れていることがわかります。
したがって自己回帰ラグの値は **P = 1** となります。

## 2.2. モデル作成ステップ
### 2.2.(1) ARIMAモデルの係数を取得
**TD_ARIMAESTIMATE関数**は ARIMAモデルに対応する係数を推定し 既存のARIMAモデルに系列を適合させます。
この関数は 「適合度」と適合操作の残差も提供することができます。
TD_ARIMAVALIDATE関数とTD_ARIMAFORECAST関数の入力として使用されるモデル層を生成する関数です。この関数は一変量系列を対象としています。

MODEL_ORDER(P, d, Q)には これまでのステップで推定した P、d、Q パラメータを使用して MODEL_ORDER(1, 1, 3)とします。
出力結果は ART(出力テーブル) に格納されます。
適合率は 80とします。ARIMAモデルがデータの80%でトレーニングし 残りの20%のデータはモデルの検証に使用します。

次のクエリは **[TD_ARIMAESTIMATE](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/Teradata-VantageTM-Unbounded-Array-Framework%E6%99%82%E7%B3%BB%E5%88%97%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-17.20/%E3%83%A2%E3%83%86%E3%83%AB%E6%BA%96%E5%82%99%E9%96%A2%E6%95%B0%E3%81%8A%E3%82%88%E3%81%B2%E3%83%8F%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E6%8E%A8%E5%AE%9A%E9%96%A2%E6%95%B0/TD_ARIMAESTIMATE)** を使ってARIMAモデルに対応する係数を推定し 既存のARIMAモデルと系列を適合させます。
```SQL:TD_ARIMAESTIMATE関数
EXECUTE FUNCTION INTO VOLATILE ART(ART_EST)
TD_ARIMAESTIMATE(
    SERIES_SPEC(
        TABLE_NAME(DEMO_AirPassengers.airpassengers),
        ROW_AXIS(TIMECODE("Date")),
        SERIES_ID(seriesID),
        PAYLOAD(
            FIELDS("Passengers"),
            CONTENT(REAL))),
     FUNC_PARAMS(
        NONSEASONAL(MODEL_ORDER(1, 1, 3)),
        SEASONAL(MODEL_ORDER(1, 1, 3), PERIOD(12)),
        CONSTANT(1), COEFF_STATS(1), FIT_METRICS(1),
        RESIDUALS(1), ALGORITHM(CSS_MLE),  FIT_PERCENTAGE(80)
    )
);
```

### 2.2.(2) 残差の抽出
**TD_EXTRACT_RESULTS関数**は ART(出力テーブル)に格納されている補助結果セットを取得します。
ここでは ARTから残差を抽出します。
分析結果テーブルには異なるデータを格納する複数のレイヤーがあります。
デフォルトのレイヤーにはモデル情報が格納されています。
**ARTFITRESIDUALSレイヤー** は 実際値、計算値、残差 の情報を持っています。**ARTFITMETADATAレイヤー** は パフォーマンス・メトリクスを持ちます。

次のクエリは 作成したテーブルに **[TD_EXTRACT_RESULTS](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/Teradata-VantageTM-Unbounded-Array-Framework%E6%99%82%E7%B3%BB%E5%88%97%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-17.20/%E6%B1%8E%E7%94%A8%E3%83%A6%E3%83%BC%E3%83%86%E3%82%A3%E3%83%AA%E3%83%86%E3%82%A3%E9%96%A2%E6%95%B0/TD_EXTRACT_RESULTS)** を使って ARTFITRESIDUALSレイヤーを抽出し格納します。

```SQL:TD_EXTRACT_RESULTS関数
CREATE TABLE AR_RESIDUALS AS (
    EXECUTE FUNCTION
    TD_EXTRACT_RESULTS(
        ART_SPEC(
            TABLE_NAME(ART_EST),
            LAYER(ARTFITRESIDUALS)
        )
    )
) WITH DATA;
```
```SQL
SELECT TOP 5 * FROM AR_RESIDUALS ORDER BY ROW_I;
```
|seriesID|ROW_I|ACTUAL_VALUE|CALC_VALUE|RESIDUAL|
|:-|:-|:-|:-|:-|
|FlyHigh|0|112|111.93533678259698|0.06466321740301692|
|FlyHigh|1|118|117.9664341620197|0.033565837980311194|
|FlyHigh|2|132|131.96619386853047|0.03380613146952975|
|FlyHigh|3|129|128.97744816594982|0.022551834050185737|
|FlyHigh|4|121|120.9892461371173|0.010753862882700261|

この値はARIMAモデルの実績値、計算値、残差です。
実績値は搭乗者数を示しています。
計算値は推定段階でモデルが学習した内容を示しています。
残差は実際の値と計算値の差です。

次のクエリは 作成したテーブルに **[TD_EXTRACT_RESULTS](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/Teradata-VantageTM-Unbounded-Array-Framework%E6%99%82%E7%B3%BB%E5%88%97%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-17.20/%E6%B1%8E%E7%94%A8%E3%83%A6%E3%83%BC%E3%83%86%E3%82%A3%E3%83%AA%E3%83%86%E3%82%A3%E9%96%A2%E6%95%B0/TD_EXTRACT_RESULTS)** を使って ARTFITMETADATAレイヤを抽出し格納します。

```SQL:TD_EXTRACT_RESULTS関数
SELECT * FROM (
    EXECUTE FUNCTION
    TD_EXTRACT_RESULTS(
        ART_SPEC(
            TABLE_NAME(ART_EST),
            LAYER(ARTFITMETADATA)
        )
    )
) AS T;
```
|seriesID|ROW_I|NUM_SAMPLES|VAR_COUNT|R_SQUARE|R_ADJ_SQUARE|STD_ERROR|STD_ERROR_DF|ME|MAE|MSE|MPE|MAPE|FSTAT_CALC|P_VALUE|NUM_DF|DENOM_DF|SIGNIFICANCE_LEVEL|F_CRITICAL|F_CRITICAL_P|NULL_HYPOTH|
|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|:-|
|FlyHigh|0|115|8|0.991091251376211|0.9905084360456827|75.642224556571|113|0.6063622781093305|6.422070579408627|74.32670760776107|0.2532102004518045|2.677695324371721|1700.5236469636197|1.379855387071475e-106|7|107|0.05|2.0963213718883407|0.05|REJECT|

この結果は ARIMAモデルがどの程度うまく学習できたかを示す性能指標を示しています。
例えばR_SQUAREDの値は0.99です。これはモデルがデータによく適合していることを示唆しています。
R_SQUAREDの値が高いほどモデルがデータによく適合していることを意味します。R_SQUAREDの値は 0から1までの範囲です。

### 2.2.(3) プロット用テーブルPLOT_ESTIMATEの作成
```SQL:PLOT_ESTIMATEテーブルの作成
CREATE TABLE PLOT_ESTIMATE (DatasetID VARCHAR(10), ROW_I BIGINT, FIT_MAGNITUDE FLOAT);
INSERT INTO PLOT_ESTIMATE SELECT 'FlyHigh', ROW_I, ACTUAL_VALUE FROM AR_RESIDUALS WHERE ROW_I>1; 
INSERT INTO PLOT_ESTIMATE SELECT 'ESTIMATED', ROW_I, CALC_VALUE FROM AR_RESIDUALS WHERE ROW_I>1; 
```
```SQL
SELECT TOP 5 * FROM PLOT_ESTIMATE ORDER BY ROW_I;
```
|DatasetID|ROW_I|FIT_MAGNITUDE|
|:-|:-|:-|
|ESTIMATED|2|131.96619386853047|
|FlyHigh|2|132|
|ESTIMATED|3|128.97744816594982|
|FlyHigh|3|129|
|FlyHigh|4|121|

実値と予測値の比較をグラフで確認する。
```SQL:TD_Plot関数
EXECUTE FUNCTION
TD_Plot
(
    SERIES_SPEC(
        TABLE_NAME(PLOT_ESTIMATE),
        ROW_AXIS(SEQUENCE(ROW_I)),
        SERIES_ID(DataSetID),
        ID_SEQUENCE('[{"DatasetID":"FlyHigh"},{"DatasetID":"ESTIMATED"}]'),
        PAYLOAD(
            FIELDS(FIT_MAGNITUDE),
            CONTENT(REAL)
        )
    ),
    FUNC_PARAMS
    (
        WIDTH(1920),
        HEIGHT(1080),
        TITLE('ARIMA ESTIMATE'),
        PLOTS[
            (
                TITLE ('ORIGINAL and ESTIMATED SERIES'),
                GRID(FORMAT('-')),
                TYPE('line'),
                SERIES[
                       (
                        ID(1),
                        FORMAT('r--')
                       ),
                       (
                        ID(2),
                        FORMAT('b-')
                       )
                     ],
                MARKER('o'),
                LEGEND('best'),
                XLABEL('X SeqNo'),
                YLABEL('Y Magnitude')
            )
        ]
    )
);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778293/8356b7d8-c005-2c68-b9d7-cf6f26bd7d32.png)

赤線は実際の乗客数 青線は推定乗客数を示しています。
このグラフはARIMAモデルがトレーニングデータセットに対してどの程度学習したかを示しています。

## 2.3. 検証ステップ
### 2.3.(1) 検証
TD_ARIMAVALIDATE関数はデータ科学者にモデル選択と生成された残差のためのメトリクスコレクションを提供し複数のモデル検証テストを実行することができます。TD_ARIMAVALIDATE関数は季節性・非季節性の自己回帰（AR）、移動平均（MA）、ARIMAモデルについてサンプル内予測を実行することができます。
また、拡張Box Jenkins季節性ARIMAモデル式もサポートしています。

推定ステップの出力を使ってモデルの検証を行います。
データセットのtrain-validateの分割は80：20です。
したがって、推定されたモデルを検証するためにデータの20％が使用されることになります。

```SQL:TD_ARIMAVALIDATE関数
EXECUTE FUNCTION 
INTO VOLATILE ART(AR_VALIDATE)
TD_ARIMAVALIDATE(
    ART_SPEC(TABLE_NAME(ART_EST)),
    FUNC_PARAMS(
        FIT_METRICS(1),
        RESIDUALS(1)
    )
);
```

### 2.3.(2) 残差の抽出
TD_EXTRACT_RESULTS関数はARTに格納されている補助結果セットを取得します。
ここでは、検証ステップのARTテーブル出力から残差を抽出します。
```SQL:AR_VALIDATE_RESIDUALSテーブルの作成
CREATE TABLE AR_VALIDATE_RESIDUALS AS (
    EXECUTE FUNCTION 
    TD_EXTRACT_RESULTS(
        ART_SPEC(
            TABLE_NAME(AR_VALIDATE),
            LAYER(ARTFITRESIDUALS)
        )
    )
) WITH DATA;
```
```SQL
SELECT TOP 5 * FROM AR_VALIDATE_RESIDUALS ORDER BY ROW_I;
```
|seriesID|ROW_I|ACTUAL_VALUE|CALC_VALUE|RESIDUAL|
|:-|:-|:-|:-|:-|
|FlyHigh|102|505|504.71541606026983|0.2845839397301829|
|FlyHigh|103|404|403.9536743499105|0.04632565008948548|
|FlyHigh|104|359|359.00708485101035|-0.007084851010358043|
|FlyHigh|105|310|310.0491891859232|-0.0491891859232049|
|FlyHigh|106|337|337.01793845433355|-0.01793845433357069|

検証フェーズのARIMAモデルの実績値、計算値、残差です。
実測値は未公開データ（検証データ）の乗客数です。
計算値は未公開データに対するARIMAモデルによる予測値です。

検証フェーズの出力であるARTから再びメタデータを引き出します。
```SQL:TD_EXTRACT_RESULTS関数
SELECT * FROM (
    EXECUTE FUNCTION
    TD_EXTRACT_RESULTS(
        ART_SPEC(
            TABLE_NAME(AR_VALIDATE),
            LAYER(ARTFITMETADATA)
        )
    )
) AS T;
```

検証フェーズのパフォーマンスメトリクスを示します。
これらのメトリクスは未見のデータセット、すなわち検証用データセットにおいて、我々のモデルがどの程度優れた性能を発揮するかを分析するのに役立ちます。
例えばこの出力から得られるR_SQUAREDの値は0.97であり、これは良い値です。R_SQUAREDの値が高いほど優れたモデルであることを意味します。
R_SQUARED値の範囲は0から1までです。

### 2.3.(3) PLOT_VALIDATEテーブルを作成する
```SQL:PLOT_VALIDATEテーブルの作成
CREATE TABLE PLOT_VALIDATE (DatasetID VARCHAR(10), ROW_I BIGINT, FIT_MAGNITUDE FLOAT);
INSERT INTO PLOT_VALIDATE SELECT 'FlyHigh', ROW_I, ACTUAL_VALUE FROM AR_VALIDATE_RESIDUALS WHERE ROW_I>0; 
INSERT INTO PLOT_VALIDATE SELECT 'PREDICTED', ROW_I, CALC_VALUE FROM AR_VALIDATE_RESIDUALS WHERE ROW_I>0;
```
```SQL
EXECUTE FUNCTION
TD_Plot
(
    SERIES_SPEC(
        TABLE_NAME(PLOT_VALIDATE),
        ROW_AXIS(SEQUENCE(ROW_I)),
        SERIES_ID(DataSetID),
        ID_SEQUENCE('[{"DatasetID":"FlyHigh"},{"DatasetID":"PREDICTED"}]'),
        PAYLOAD(
            FIELDS(FIT_MAGNITUDE),
            CONTENT(REAL)
        )
    ),
    FUNC_PARAMS
    (
        WIDTH(1920),
        HEIGHT(1080),
        TITLE('ARIMA VALIDATE'),
        PLOTS[
            (
                TITLE ('ORIGINAL and PREDICTED SERIES'),
                GRID(FORMAT('-')),
                TYPE('line'),
                SERIES[
                       (
                        ID(1),
                        FORMAT('r--')
                       ),
                       (
                        ID(2),
                        FORMAT('b-')
                       )
                     ],
                MARKER('o'),
                LEGEND('best'),
                XLABEL('X SeqNo'),
                YLABEL('Y Magnitude')
            )
        ]
    )
);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778293/755af639-fef8-4ed1-e35f-ca723483cb31.png)

赤線が実際の搭乗者数、青線が予測搭乗者数です。
このグラフは、検証データに対してARIMAモデルがどの程度予測できたかを示しています。

## 2.4. 予測ステップ
### 2.4.(1) 予測
TD_ARIMAFORECAST関数は、TD_ARIMAESTIMATE関数からフィッティングされたモデルに基づいて、ユーザーが定義した数の期間を予測するために使用されます。

ここでは、次のセルで、推定・検証されたモデルを使用して、その後の6期間、つまり今後6ヶ月間の乗客数を予測します。
```SQL
EXECUTE FUNCTION INTO VOLATILE ART(ARMA_FORECAST)
TD_ARIMAFORECAST(
           ART_SPEC(TABLE_NAME(AR_VALIDATE)),
           FUNC_PARAMS(FORECAST_PERIODS(6)));
```
```SQL
SELECT * FROM ARMA_FORECAST;
```

|seriesID|ROW_I|FORECAST_VALUE|LO_80|HI_80|LO_95|HI_95|
|:-|:-|:-|:-|:-|:-|:-|
|FlyHigh|0|448.80286816861485|437.05108030679287|460.55465603043683|430.8300655474117|466.775670789818|
|FlyHigh|1|422.45446369929124|407.3437819074814|437.5651454911011|399.3446778088999|445.56424958968256|
|FlyHigh|2|470.4832626708105|452.0389194713592|488.92760587026186|442.27508331127655|498.6914420303445|
|FlyHigh|3|506.76582797603453|486.9446633054949|526.5869926465742|476.4519825820672|537.0796733700018|
|FlyHigh|4|530.0389185693377|509.4219846866439|550.6558524520316|498.50804959136406|561.5697875473114|
|FlyHigh|5|570.6776110806936|549.4849395681031|591.8702825932842|538.2662276733071|603.0889944880802|

この結果は今後6ヶ月間の予測値を示しています。
信頼度80％と95％の予測値も出ていることに注目してください。

### 2.4.(2) PLOT_FORECAST表を作成する。
```SQL:PLOT_FORECASTテーブルの作成
CREATE TABLE PLOT_FORECAST (DatasetID VARCHAR(16), ROW_I BIGINT, FORECAST_MAGNITUDE FLOAT);

INSERT INTO PLOT_FORECAST   SELECT 'FORECASTED', ROW_I, FORECAST_VALUE FROM ARMA_FORECAST; 
INSERT INTO PLOT_FORECAST   SELECT 'UPPER_BOUND', ROW_I, HI_80 FROM ARMA_FORECAST ; 
INSERT INTO PLOT_FORECAST   SELECT 'LOWER_BOUND', ROW_I, LO_80 FROM ARMA_FORECAST ; 
```
```SQL
EXECUTE FUNCTION
TD_Plot
(
    SERIES_SPEC(
        TABLE_NAME(PLOT_FORECAST),
        ROW_AXIS(SEQUENCE(ROW_I)),
        SERIES_ID(DataSetID),
        ID_SEQUENCE('[{"DatasetID":"FORECASTED"},{"DatasetID":"UPPER_BOUND"},{"DatasetID":"LOWER_BOUND"}]'),
        PAYLOAD(
            FIELDS(FORECAST_MAGNITUDE),
            CONTENT(REAL)
        )
    ),
    FUNC_PARAMS
    (
        WIDTH(1920),
        HEIGHT(1080),
        TITLE('ARIMA FORECAST'),
        PLOTS[
            (
                TITLE ('Forecast'),
                GRID(FORMAT('-')),
                TYPE('line'),
                SERIES[
                       (
                        ID(1),
                        FORMAT('r--')
                       ),
                       (
                        ID(2),
                        FORMAT('b-')
                       ),
                        (
                        ID(3),
                        FORMAT('b-')
                       )
                     ],
                MARKER('o'),
                LEGEND('best'),
                XLABEL('X SeqNo'),
                YLABEL('Y Magnitude')
            )
        ]
    )
);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778293/3a1443e1-5485-ed17-04bf-0af3102a1faa.png)

赤線は今後6ヶ月間の予測搭乗者数、青線は信頼度80％の上下の信頼区間です。


# 3. 結論
航空旅客データセットでARIMAモデルの学習と検証を行いましたが、結果は実際のデータと密接に一致しています。推定と検証の段階で計算された適合度メトリクスも、このモデルが予測のためによく訓練されているという我々の理解に共鳴しています。

# おわりに
:::note warn
警告
この本書は[Teradata Vantageドキュメンテーション](https://docs.teradata.com/)よりトピックに必要な情報を抜粋したものです。掲載内容の正確性・完全性・信頼性・最新性を保証するものではございません。正確な内容については、原本をご参照下さい。
また、修正が必要な箇所や、ご要望についてはコメントをよろしくお願いします。
:::
## Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)