時系列予測の 3 つの方法: 統計モデル、機械学習、リカレント ニューラル ネットワーク

ガイド

時系列予測は古典的な問題の一種であり、学術界や産業界で広く研究され、応用されてきました。株価や天候の変化など、世界のあらゆるものは時間の次元を加えて時系列問題に抽象化できるとも言われています。時系列予測に関連する理論も非常に広範囲にわたり、さまざまな古典的な統計モデルに加えて、現在人気のある機械学習および深層学習サイクリック ニューラル ネットワークも時系列予測問題のモデル化に使用できます。今日、この記事では 3 つの方法の簡単な適用を紹介し、それらをリアルタイムの時系列データ セットで検証します。

41ba44eb6818568c0aea8d12cdd412ad.png

時系列予測の主なタスクは、特定の指標の履歴データに基づいて将来の値を予測することです。たとえば、上の図の曲線は、1949 年から 1949 年までの 12 年 144 か月間の月間航空乗客数を記録しています。 1960 年 (具体的な単位は検証されていない) の場合、時系列予測で解決すべき問題は次のとおりです。1949 年から 1957 年など、最初の 9 年間の履歴データが与えられた場合、1958 年からの 2 年間の乗客数は次のとおりです。 -1960年が予測されます。

この問題を解決するには、おそらく 4 つの主流の解決策があります。

  • 統計モデル、AR、MA、ARMA、ARIMA などのより古典的な AR シリーズ。また、Facebook が発表した Prophet モデル (正確に言うと、今ではメタと呼ぶべきです) は、本質的には統計モデルですが、より正確なタイミング ルールを実現するために、従来のトレンドと周期的なコンポーネントの基礎、休日やタイミング変曲点などの要因の影響がさらに詳細に考慮されます。

  • 機械学習モデル、教師あり機械学習では、回帰問題は主に、一連の特徴に基づいてラベルの取り得る値を予測する問題を解決します。そのため、履歴データが特徴として使用される場合、時系列を使用するのが自然です。予測問題 回帰問題として抽象化されているため、この観点から見ると、すべての回帰モデルを使用して時系列予測を解決できます。機械学習を使用した抽象的な時系列予測については、この論文「時系列予測のための機械学習戦略」を参照することをお勧めします。

  • 深層学習モデル、深層学習の主流のアプリケーション シナリオは CV と NLP で、後者は特にシーケンス問題モデリングの問題を解決するために使用されます。時系列はもちろんシーケンス データの特別な形式であるため、リカレント ニューラル ネットワークを使用して時系列予測をモデル化する。

  • 隠れマルコフ モデル、マルコフ モデルは、隣接する状態間の遷移を記述するために使用される古典的な抽象化であり、隠れマルコフ モデルはさらに隠れ状態を追加してモデルの表現能力を豊かにします。ただし、主要な前提の 1 つは、将来の状態は現在の状態にのみ関連しており、予測に参加するために複数の過去の状態を使用することは役に立たないということです。より一般的に使用されるのは、天気予報の例です。

この論文では主に最初の 3 つの時系列予測モデリング手法を検討し、テストする 1) Prophet モデル、2) RandomForest 回帰モデル、3) LSTM の 3 つのスキームを選択します。

まず、飛行機の乗客の実際のデータセットでテストし、選択した 3 つのモデルの予測精度を順番に比較します。データ セットには合計 12 年間の月ごとの乗客数が含まれています。1958 年 1 月がトレーニング セットとテスト セットを分割するためのセグメンテーション インターフェイスとして使用されます。つまり、最初の 9 年間のデータがトレーニング セットとして使用されます。過去 3 年間のデータは、モデルの効果を検証するためのテスト セットとして使用されます。セグメンテーション後のデータセットの概略図は次のとおりです。

df = pd.read_csv("AirPassengers.csv", parse_dates=["date"]).rename(columns={"date":"ds", "value":"y"})
X_train = df[df.ds<"19580101"]
X_test = df[df.ds>="19580101"]


plt.plot(X_train['ds'], X_train['y'])
plt.plot(X_test['ds'], X_test['y'])

814250cf0fb15a619f6c0dfc4acf8449.png

1. 預言者モデルの予測Prophet は、高度にカプセル化された時系列予測モデルであり、トレーニング セットとして DataFrame を受け入れ (ds および y フィールド列が必要です)、予測時に DataFrame も受け入れますが、現時点で必要なのは ds 列のみです。詳細な紹介については、公式ドキュメント https://facebook.github.io/prophet/ を参照してください。モデルのトレーニングと予測のコア コードは次のとおりです。

from prophet import Prophet
pro = Prophet()
pro.fit(X_train)
pred = pro.predict(X_test)


pro.plot(pred)

トレーニング結果の模式図は次のとおりです。

9ef951b63e2a3c9f30193a3d04731410.png

もちろん、これは Prophet の組み込み視覚化機能によって、またはテスト セットの実際のラベルと予測結果の比較を手動で描画することによって得られた結果です。

4447ef206f0387df9ca2e7b49453c3ed.png

シリーズの全体的な傾向は良好なフィッティング結果を示していますが、実際には特定の値には比較的大きなギャップがあることが簡単にわかります。

2. 機械学習モデル、ここではさまざまなベースラインとしてよく使用される RandomForest モデルを選択します。機械学習を使用して時系列予測を実現する場合、通常、スライディング ウィンドウを通じて特徴とラベルを抽出し、実際に予測を実現するときにシングル ステップ予測を達成するためにテスト セットの特徴をスライドおよびインターセプトする必要があります。論文「機械学習」を参照してください。時間に対する学習戦略 シリーズ予測の実践における問題は、次のように大まかに説明できます。

6b3cd2f6df33efb311d2fe129c96875c.png

したがって、特徴抽出ウィンドウの長さは 12 に設定され、トレーニング セットとテスト セットの構築方法は次のようになります。

data = df.copy()
n = 12
for i in range(1, n+1):
    data['ypre_'+str(i)] = data['y'].shift(i)
data = data[['ds']+['ypre_'+str(i) for i in range(n, 0, -1)]+['y']]


# 提取训练集和测试集
X_train = data[data['ds']<"19580101"].dropna()[['ypre_'+str(i) for i in range(n, 0, -1)]]
y_train = data[data['ds']<"19580101"].dropna()[['y']]
X_test = data[data['ds']>="19580101"].dropna()[['ypre_'+str(i) for i in range(n, 0, -1)]]
y_test = data[data['ds']>="19580101"].dropna()[['y']]


# 模型训练和预测
rf = RandomForestRegressor(n_estimators=10, max_depth=5)
rf.fit(X_train, y_train)
y_pred = rf.predict(X_test)


# 结果对比绘图
y_test.assign(yhat=y_pred).plot()

9b87062d7a7b35e74cb5cf4d8b77474d.png

予測効果は比較的一般的であることがわかり、特に過去 2 年間の予測結果では、実際の値とのギャップが依然として比較的大きいことがわかります。この現象は機械学習モデルの考え方で説明するのが簡単です: ランダム フォレスト モデルは実際にトレーニング データ セットに従って曲線の間の法則を学習しています。時系列全体としては時間の経過とともに増加する傾向を示しているため、履歴データの最高点将来のより大きな値をカバーするには十分ではないため、テスト セット内の履歴データを超えるすべてのラベルは実際には適合できません。

3. ディープ ラーニングのサイクリック ニューラル ネットワーク。実際、ディープ ラーニングでは一般に、その利点を最大限に発揮するには大規模なデータ セットが必要です。ここでのデータ セットは明らかに非常に小さいため、最も単純なモデルの 1 つだけが設計されています。層 LSTM+1 層線形。モデルは次のように構築されます。

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.rnn = nn.LSTM(input_size=1, hidden_size=10, batch_first=True)
        self.linear = nn.Linear(10, 1)
        
    def forward(self, x):
        x, _ = self.rnn(x)
        x = x[:, -1, :]
        x = self.linear(x)
        return x

データセット構築の全体的な考え方は前述の機械学習部分と同じであり、モデルトレーニング錬金術によれば、いくつかの結果は次のようになります。

# 数据集转化为3D
X_train_3d = torch.Tensor(X_train.values).reshape(*X_train.shape, 1)
y_train_2d = torch.Tensor(y_train.values).reshape(*y_train.shape, 1)
X_test_3d = torch.Tensor(X_test.values).reshape(*X_test.shape, 1)
y_test_2d = torch.Tensor(y_test.values).reshape(*y_test.shape, 1)


# 模型、优化器、评估准则
model = Model()
creterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters())


# 训练过程
for i in range(1000):
    out = model(X_train_3d)
    loss = creterion(out, y_train_2d)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    
    if (i+1)%100 == 0:
        y_pred = model(X_test_3d)
        loss_test = creterion(y_pred, y_test_2d)
        print(i, loss.item(), loss_test.item())


# 训练结果
99 65492.08984375 188633.796875
199 64814.4375 187436.4375
299 64462.09765625 186815.5
399 64142.70703125 186251.125
499 63835.5 185707.46875
599 63535.15234375 185175.1875
699 63239.39453125 184650.46875
799 62947.08203125 184131.21875
899 62657.484375 183616.203125
999 62370.171875 183104.671875

上記の 1000 エポックを通じて、モデルがうまく適合しないことが大まかに推測できるため、思い切ってあきらめてください。

もちろん、上記のテスト結果は、このデータ セットでの 3 つのスキームのパフォーマンスを示すだけであり、時系列予測問題で使用した場合のこのタイプのモデルのパフォーマンスを表すことはできないことに注意する必要があります。実際、時系列予測問題自体は、特定の問題の具体的な分析が必要なシナリオであり、「フリー ランチなし」と同じように、普遍的に適用できる優れたモデルはありません。

この記事は時系列予測一連のツイートの小さなテストにすぎず、その他の関連する体験談や概要は今後随時更新されます。

458f1d9784c2b30bb45d4832a81440f6.png

関連書籍:

おすすめ

転載: blog.csdn.net/weixin_43841688/article/details/122053781