AI学習者・実務家の「疑問」を解消する

外資系IT企業で、主に火力発電所のAI最適化に従事 →2019年6月: 米国SAS社が主催する ”SaS Analytics Hackathon”で優勝

LSTMをよりわかりやすく&より詳細に!(前処理・python実践編)

モチベーション

LSTMを使う際、実際に必要な前処理のコーディングを解説します。

本記事は、実践編なので、

LSTMのデータ準備の世界観の説明は省略し、
pythonでの実践的なコーディングのみを説明します。

LSTMのデータ準備の世界観が知りたい!!という方は、
是非この記事を参考にしてください:)
https://akenkenken.hatenablog.com/entry/2019/09/29/205040akenkenken.hatenablog.com

データセットについて

データは、前回の記事(https://akenkenken.hatenablog.com/entry/2019/09/29/205040)で説明した通り、
中国の大気汚染(PM2.5)のデータセットを使用します。

f:id:akenkenken:20190929183559p:plain
出典:UCI Machine Learning Repository

データの保存は、こちらからできます:)
https://raw.githubusercontent.com/jbrownlee/Datasets/master/pollution.csv

本編:Pythonでどう表現するのか?

まず、基本的な前処理を一気にやってしまいます。

### 前処理 ###
"""
前処理で考慮したポイント
1. 時間の情報が、'year', 'month', 'day', 'hour'でバラバラになっているので、繋げる(for文は禁止!!!)
2. 最初の24時間、連続して、PM2.5の値が欠損しているので、そこはDrop(その他は、0で欠損補完)
3. その他、今記事で取り扱う上で、不要なコラム(”NO”)の削除
"""
# ライブラリのインポート
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


#データの読み込み
df            = pd.read_csv("pollution.csv", parse_dates = [['year', 'month', 'day', 'hour']], 
                            index_col=0).drop("No", axis=1)
df.index.name = "timestamp"
df.columns    = ['PM2.5', 'dew_point', 'temp', 'pressure', 'wind_direction', 'wind_speed', 'snow', 'rain']


#時間情報を適切な形に変換する
"""
データの前処理で、for文を使うのは、なるべく避けてください。処理が遅くなっちゃうので。
今回は、apply関数を使用しています。
"""
df = df.reset_index()
def datetime_format_changer(x):
    return datetime.strptime(x, '%Y %m %d %H')
df["timestamp"] = df["timestamp"].apply(datetime_format_changer)
df = df.set_index("timestamp")


# 欠損値の処理
"""
欠損値処理は、いろんな論点があり、本来はもっとまじめにやるべきですが、
本記事では割愛させていただきます<(_ _)>
"""
# print("最初の24時間、PM2.5が欠損しているのを確認!!")
# print("-----------------------------------------")
# print(df[:24])

df = df[24:]
df.fillna(0, inplace=True)
df.head()


上記のコードを実行したら、こんなoutputが出てくるはず。
f:id:akenkenken:20191006174923p:plain


さて、基本的な前処理が終了したので、いよいよLSTMのために、
データを準備します。

今回は、2つのパターンを例とします。

パターン1: 1変数での予測

  • ターゲット:PM2.5 
  • 説明変数 :PM2.5(2分前), PM2.5(1分前)

パターン2:2変数での予測

  • ターゲット:PM2.5 
  • 説明変数 :PM2.5(2分前), PM2.5(1分前), temp(2分前), temp(1分前)
# 関数の定義
def create_dataset(dataset, look_back):
    dataX, dataY = [], []
    for i in range(len(dataset)-look_back-1):
        xset = []
        for j in range(dataset.shape[1]):
            a = dataset.iloc[i:i+look_back, j]
            xset.append(a)
        dataY.append(dataset.iloc[i+look_back, 0])      
        dataX.append(xset)
    return np.array(dataX), np.array(dataY)

# パターン1
a = df.loc[:, ['PM2.5']].head(100) 
x_pattern1, y_pattern1 = create_dataset(dataset=a, look_back=2)

# パターン2
a = df.loc[:, ['PM2.5',"temp"]].head(100) 
x_pattern2, y_pattern2 = create_dataset(dataset=a, look_back=2)

パターン1の方は、1変数で予測してるので、
下記の図のようなイメージ。

f:id:akenkenken:20191007145624p:plain
パターン1のイメージ

パターン2の方は、2変数で予測してるので、
下記の図のようなイメージ。

f:id:akenkenken:20191007144427p:plain
パターン2のイメージ