K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

MA過程

中級

04.13.2

MA過程

最終更新 2020-04-08 読了時間 3 分
まとめ
MA(移動平均)過程は、今日の値を「平均 \(\mu\) + 今日のノイズ \(\epsilon_t\) + 過去 \(q\) 期分のノイズに係数 \(\theta_j\) を掛けたもの」で表す確率過程です。AR 過程が過去の値を引きずるのに対し、MA 過程は過去のノイズだけを \(q\) 期だけ引きずり、それより前の影響は完全に消えます。このページでは create_MAdata という 13 行の関数で MA(1)・MA(2)・MA(10) の系列を 400 点ずつ生成し、係数の個数が増えると揺れがなめらかになる様子を図で確かめます。読み終えると、ACF が \(q\) 期で途切れる系列を見て「MA(q) らしい」と判断する手がかりが持てます。

AR過程 で「過去の値を係数 \(\phi\) で引きずる」仕組みを先に見ておくと、MA 過程との違い(引きずるのがノイズか値か)がはっきりします。


直感 #

毎日の売上を記録していて、ある日テレビで紹介されて売上が急に跳ねたとします。その「驚き」は翌日も少し残り(在庫を見た人が買いに来る)、2 日後にはほぼ消える。この「驚き(ノイズ)が数日だけ尾を引く」構造が MA 過程です。AR 過程なら「昨日の売上が高かったから今日も高い」と値そのものを引きずりますが、MA 過程は「昨日のノイズの 0.5 倍だけ今日に乗る」と、ノイズだけを引きずります。

使うライブラリ #

1
2
3
import statsmodels.api as sm
import numpy as np
import matplotlib.pyplot as plt

何が起きているか(ステップで見る) #

コードを読む前に、この手法が図の上で何をしているかを追ってみましょう。「再生」を押すか、スライダーを動かすと 1 手順ずつ進みます。

見るポイント:MA の影響は 1 期(次数分)で消える。短い揺れの形を作る成分。

式で書くと何を足し合わせているか #

MA(q) 過程は、平均 \(\mu\)、今日のノイズ \(\epsilon_t\)、過去 \(q\) 期のノイズ \(\epsilon_{t-1}, \dots, \epsilon_{t-q}\) を係数 \(\theta_1, \dots, \theta_q\) で重みづけして足したものです。

$$ y_t = \mu + \epsilon_t + \theta_1 \epsilon_{t-1} + \theta_2 \epsilon_{t-2} + \cdots + \theta_q \epsilon_{t-q} $$

\(\epsilon_t\) は平均 0・標準偏差 \(\sigma\) の正規乱数です。式に \(y_{t-1}\) が出てこないのが AR 過程との最大の違いで、\(q+1\) 期前のノイズは係数が付かないので影響がゼロになります。自己相関関数(ACF)が \(q\) 期を過ぎると急に 0 に落ちるのはこのためで、下のコードで係数の個数 len(thetas) を 1・2・10 と変えると、ACF が途切れるラグも 1・2・10 と動きます。

MA過程のデータを生成する #

次の関数は、上の式をそのまま for ループで書き下したものです。thetas の長さが次数 \(q\) になり、sigma がノイズの大きさを決めます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
def create_MAdata(thetas=[0.1], mu=1, N=400, init=1, c=1, sigma=0.3):
    """MAモデルで時系列データを生成"""
    print(f"==MA({len(thetas)})過程の長さ{N}のデータを作成==")
    epsilon = np.random.normal(loc=0, scale=sigma, size=N)
    data = np.zeros(N)
    data[0] = init

    for t in range(2, N):
        res = mu + epsilon[t]
        for j, theta_j in enumerate(thetas):
            res += theta_j * epsilon[t - j - 1]
        data[t] = res
    return data

MA(1) #

係数 1 個(\(\theta_1 = 0.5\))の系列を描きます。隣り合う点どうしだけに相関があり、2 点以上離れると無相関になります。

1
2
3
4
5
6
plt.figure(figsize=(12, 6))
thetas = [0.5]
ma1_1 = create_MAdata(thetas=thetas)
plt.title(f"MA{len(thetas)}過程", fontsize=15)
plt.plot(ma1_1)
plt.show()
==MA(1)過程の長さ400のデータを作成==

==MA(1)過程の長さ400のデータを作成==の図

MA(2) #

係数を 2 個(\(\theta_1 = \theta_2 = 0.5\))にすると、2 期前のノイズまで今日に乗ります。

1
2
3
4
5
6
plt.figure(figsize=(12, 6))
thetas = [0.5, 0.5]
ma1_2 = create_MAdata(thetas=thetas)
plt.title(f"MA{len(thetas)}過程", fontsize=15)
plt.plot(ma1_1)
plt.show()
==MA(2)過程の長さ400のデータを作成==

==MA(2)過程の長さ400のデータを作成==の図

MA(10)(係数を 10 個にする) #

係数を 10 個並べると、10 期前までのノイズが足し合わさります。ノイズを 11 個分平均するような効果が出るため、短い揺れが打ち消されてうねりだけが残ります。

1
2
3
4
5
6
plt.figure(figsize=(12, 6))
thetas = [0.5 for _ in range(10)]
ma1_5 = create_MAdata(thetas=thetas)
plt.title(f"MA{len(thetas)}過程", fontsize=15)
plt.plot(ma1_5)
plt.show()
==MA(10)過程の長さ400のデータを作成==

==MA(10)過程の長さ400のデータを作成==の図

使いどころと落とし穴 #

MA 過程を実データに当てるときは、まず ACF を描いて「どのラグで 0 に落ちるか」を見ます。ラグ \(q\) で急に途切れれば MA(q)、ゆっくり減衰すれば AR の疑いが強く、両方の性質が混ざっていれば ARMA を検討します。MA 過程は \(y_{t-1}\) を含まないので常に定常で、AR 過程のように \(|\phi| < 1\) を気にする必要はありません。ただし推定時には「反転可能性」(\(|\theta| < 1\) に相当する条件)が必要で、statsmodels の ARIMA(order=(0, 0, q)) はこの条件を満たす解を返します。上のコードのように np.random.seed を固定していないと、再実行ごとに図が変わる点にも注意してください。