見出し画像

第4回 時系列分析~ディープラーニング編~

はじめに

前回の記事では、時系列分析で良く用いられる"状態空間モデル"について説明し、Pythonでの実装例について紹介しました。

今回は、ディープラーニングを用いた時系列モデルである”RNN”について説明します。

RNNとは

RNNはRecurrent Neural Networksの略で、日本語では再帰型ニューラルネットワークと呼ばれます。RNNの説明に入る前に、まずは一般的なニューラルネットワークについて説明します。

本記事を読んでくださっている方の中には、以下のような図を見たことがある方もいらっしゃるのではないでしょうか?

上記のようなニューラルネットワークを順伝播型ニューラルネットワークと呼びます。順伝播型ニューラルネットワークでは入力層、隠れ層、出力層と一方向のみに情報を伝播させます。順伝播型ニューラルネットワークは非常に単純な構造をしているため理解しやすいというメリットがある一方で、時系列データに適用した場合に順序情報を正しく学習することができないというデメリットがあります。

RNNでは、上記のような時系列データに適用した場合の問題点を解消すべく、以下のような構造をしております。

RNNでは$${x_1, x_2, x_3, \cdots}$$と時系列データが入力された場合に、隠れ層の出力を出力層だけではなく、次の時刻の隠れ層の入力にすることで、時系列情報を学習することができるようになっています。

Pythonでの実装例

ここからPythonでの実装例をご紹介します。今回はPyTorchを使用してRNNの実装をします。使用したPythonのバージョンや各種ライブラリの情報は以下の通りです。

python: 3.7.3
matplotlib: 3.4.3
pandas: 1.3.3
scikit-learn: 1.0
torch: 1.10.0

今回も前回までの記事と同様に、飛行機の乗客者数のデータセットを使いたいと思います。データの読み込みなどを確認したい場合には、「第2回 時系列分析~統計的手法編~」を参照ください。今回読み込むライブラリは以下となっております。

import matplotlib.pyplot as plt
import numpy as np
import os
import pandas as pd
import random
import seaborn as sns
from sklearn.preprocessing import MinMaxScaler
import torch
import torch.nn as nn

RNNを用いて乗客者数の予測をする前に、RNNを学習させるために必要なデータセットの準備が必要となります。時系列データの場合には、下図のように時系列データから説明変数と目的変数をずらしながら作成ます。下図の例では、3時点分のデータを用いて次の時点を予測するようにデータを作成しています。3時点分のデータではなく、もっと多くの過去のデータを用いたり、予測先の時点を次の時点ではなく、2時点先を予測するといったことも可能です。

上図をsliding_windows関数として定義し、説明変数xと目的変数yを取得するコードが以下となります。なお、ここではscikit-learnのMinMaxScalerを用いて乗客者数を0~1になるように正規化しておりますが、テスト区間を含んで正規化しております。実際にはテスト区間のデータは事前には入手することはできませんので、ご注意ください。

def sliding_windows(data, seq_length):
    x = []; y = []
    
    for i in range(len(data)-seq_length-1):
        _x = data[i:(i+seq_length)]
        _y = data[i+seq_length]
        x.append(_x)
        y.append(_y)
        
    return np.array(x), np.array(y)

# 0 ~ 1に正規化
sc = MinMaxScaler()
passengers = df[['#Passengers']].values
passengers = sc.fit_transform(passengers)

# データセットの作成
seq_length = 12
x, y = sliding_windows(passengers, seq_length)

# 学習・テスト区間の全データ
data_x = torch.Tensor(x)
data_y = torch.Tensor(y)

# 学習区間のデータ
train_x = torch.Tensor(x[:len(passengers)-13])
train_y = torch.Tensor(y[:len(passengers)-13])

次にRNNを実装します。torch.nnにRNNの実装があるので、適切な引数を設定し、torch.nn.Linearで乗客者数の予測結果を出力できるようにします。RNNの引数に関しては公式ドキュメントを参照ください。

class RNN(nn.Module):
    
    def __init__(self, num_classes, input_size, hidden_size, num_layers):
        super(RNN, self).__init__()
        
        self.num_classes = num_classes
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        
        self.rnn = nn.RNN(input_size=input_size,
                          hidden_size=hidden_size,
                          num_layers=num_layers,
                          batch_first=True)
        self.fc = nn.Linear(hidden_size, num_classes)
        
    def forward(self, x):
        h_0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size)
        
        h_out, h_0 = self.rnn(x, h_0)
        h_out = h_out[:, -1, :]
        out = self.fc(h_out)
        
        return out

次に学習に必要な設定と損失関数、最適化アルゴリズムを設定します。

num_epochs = 1000
lr = 0.01

input_size = 1
hidden_size = 2
num_layers = 1
num_classes = 1

model = RNN(num_classes, input_size, hidden_size, num_layers)

critetion = torch.nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr)

最後に学習コードです。今回は1000エポック学習させます。

for epoch in range(num_epochs):
    outputs = model(train_x)
    optimizer.zero_grad()
    
    loss = critetion(outputs, train_y)
    loss.backward()
    
    optimizer.step()
    
    if epoch % 100 == 0:
        print(f'Epoch: {epoch:>4}, Loss: {loss.item():1.5f}')

予測結果をプロットしてみると、シンプルなRNNを用いただけですが、ある程度予測できていることが分かります。精度を向上させるためには、RNNの層を増やしたり、optimizerを変えてみたり、エポック数を増やしたりすることが考えられます。

まとめ

・ディープラーニングを用いた時系列モデルである”RNN”について説明しました。
・RNNは、日本語では再帰型ニューラルネットワークと呼ばれ、隠れ層の出力を次の時刻の隠れ層の入力にすることで、時系列情報を学習することができるようになっています。
・RNNをPythonで使ってみたい場合には、pytorchやtensorflowを使用すると簡単に実装することができます。

次回予告

次はPythonで用いることのできる時系列ライブラリについて紹介したいと思います。最後まで読んでいただきありがとうございました。

この記事が気に入ったらサポートをしてみませんか?