[翻訳]時系列分析、可視化、予測及びLSTMを使用

正常、安定ディッキーフラー試験の統計的試験、長期および短期記憶ネットワーク

タイトルは、すでにすべてを説明しました。

さらに騒ぎがなければ、今起動しましょう!

データ

データは1分サンプリングレートの測定における家族の消費電力である、あなたは4年近くができ、ここでは、ダウンロードしてください。

異なるパワー値と分割テーブルの数を含む数値データ。しかし、我々は、この変数Global_active_power懸念しています。

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
pd.set_option('display.float_format', lambda x: '%.4f' % x)
import seaborn as sns
sns.set_context("paper", font_scale=1.3)
sns.set_style('white')
import warnings
warnings.filterwarnings('ignore')
from time import time
import matplotlib.ticker as tkr
from scipy import stats
from statsmodels.tsa.stattools import adfuller
from sklearn import preprocessing
from statsmodels.tsa.stattools import pacf
%matplotlib inline

import math
import keras
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import Dropout
from keras.layers import *
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
from keras.callbacks import EarlyStopping

df=pd.read_csv('household_power_consumption.txt', delimiter=';')
print('Number of rows and columns:', df.shape)
df.head(5)
复制代码

表1

そして、ここで、以下のデータ前処理ステップは、プロジェクトを完了するために必要とされています。

  • 日付と時刻が同じ列にマージ、および日時型に変換しました。
  • Global_active_powerは、数値に変換され、欠損値(1.2%)を除去します。
  • フィーチャー年、四半期、月、日を作成します。
  • 週の機能を作成し、「0」週末「1」営業日。
df['date_time'] = pd.to_datetime(df['Date'] + ' ' + df['Time'])
df['Global_active_power'] = pd.to_numeric(df['Global_active_power'], errors='coerce')
df = df.dropna(subset=['Global_active_power'])
df['date_time']=pd.to_datetime(df['date_time'])
df['year'] = df['date_time'].apply(lambda x: x.year)
df['quarter'] = df['date_time'].apply(lambda x: x.quarter)
df['month'] = df['date_time'].apply(lambda x: x.month)
df['day'] = df['date_time'].apply(lambda x: x.day)
df=df.loc[:,['date_time','Global_active_power', 'year','quarter','month','day']]
df.sort_values('date_time', inplace=True, ascending=True)
df = df.reset_index(drop=True)
df["weekday"]=df.apply(lambda row: row["date_time"].weekday(),axis=1)
df["weekday"] = (df["weekday"] < 5).astype(int)

print('Number of rows and columns after removing missing values:', df.shape)
print('The time series starts from: ', df.date_time.min())
print('The time series ends on: ', df.date_time.max())
复制代码

2006年12月から2010年11月(47ヶ月)2049280の測定値の合計にデータを含む欠損値を除去した後。

初期データは、複数の変数を含みます。ここでは、単一の変数のみに焦点を当てます:家の歴史はGlobal_active_powerは、つまり、分有効電力あたりの家全体の平均消費量は、単位はキロワットです。

統計的正規性テスト

私たちのサンプルデータは、ガウス分布のように見えるかどうかを定量化するために使用することができ、いくつかの統計的検定の方法があります。私たちは、使用するダゴスティーノのK²テストを

scipyのダウンロードこのテストを実現する、我々は、p値の次のような解釈をします。

  • p <=アルファ:H0、非正規性を拒絶します。
  • P>アルファ:H0、正常性を否定するものではありません。
stat, p = stats.normaltest(df.Global_active_power)
print('Statistics=%.3f, p=%.3f' % (stat, p))
alpha = 0.05
if p > alpha:
    print('Data looks Gaussian (fail to reject H0)')
else:
    print('Data does not look Gaussian (reject H0)')
复制代码

我々はまた、計算する尖度および歪度のデータ分布が正規分布から外れているかどうかを決定するために、。

sns.distplot(df.Global_active_power);
print( 'Kurtosis of normal distribution: {}'.format(stats.kurtosis(df.Global_active_power)))
print( 'Skewness of normal distribution: {}'.format(stats.skew(df.Global_active_power)))
复制代码

図1

尖度:テール量分布説明

正規分布の尖度はゼロに近いです。ピークは、分布のテール重く、ゼロよりも大きい場合。ピークはゼロ、テールライトの分布よりも小さい場合。私たちは、尖度がゼロよりも大きくなる計算します。

歪度:分布の非対称性の尺度

歪度は、-0.5と0.5の間にある場合、データは、実質的に対称です。歪度は-0.5と-1の間にある場合、または0.5と1の間で、データが多少歪んであります。歪度が-1未満または1より大きい場合、データは非常に偏っています。私たちは、歪度が1よりも大きくなっている計算します。

最初の時系列画像

df1=df.loc[:,['date_time','Global_active_power']]
df1.set_index('date_time',inplace=True)
df1.plot(figsize=(12,5))
plt.ylabel('Global active power')
plt.legend().set_visible(False)
plt.tight_layout()
plt.title('Global Active Power Time Series')
sns.despine(top=True)
plt.show();
复制代码

図2

明らかに、これは私たちが望むイメージではありません。それをしないでください。

年次および四半期の総有効電力のボックスプロットの比較

plt.figure(figsize=(14,5))
plt.subplot(1,2,1)
plt.subplots_adjust(wspace=0.2)
sns.boxplot(x="year", y="Global_active_power", data=df)
plt.xlabel('year')
plt.title('Box plot of Yearly Global Active Power')
sns.despine(left=True)
plt.tight_layout()

plt.subplot(1,2,2)
sns.boxplot(x="quarter", y="Global_active_power", data=df)
plt.xlabel('quarter')
plt.title('Box plot of Quarterly Global Active Power')
sns.despine(left=True)
plt.tight_layout();
复制代码

図3

場合は、年間ボックスプロットの側比較による側は、我々は他の年に比べてはるかに高い2006年の中央値は、全体的な有効電力、と指摘しました。実際には、少し誤解を招くがあるでしょう。あなたは覚えていれば、私たちは、2006年12月にデータを持っています。そして、12月には、消費電力の家族のために、ピークの月であることは明らかです。

全体的な活性四半期の中央値は、第一及び第四四半期、第三四半期(夏)最小(冬)より高い、期待に沿って複数あります。

全体の有効電力配分

plt.figure(figsize=(14,6))
plt.subplot(1,2,1)
df['Global_active_power'].hist(bins=50)
plt.title('Global Active Power Distribution')

plt.subplot(1,2,2)
stats.probplot(df['Global_active_power'], plot=plt);
df1.describe().T
复制代码

図4

正規確率プロットデータも正規分布からその大きな偏差を示しています。

日、週、月、四半期および年次リサンプリング平均総有効電力により、

fig = plt.figure(figsize=(18,16))
fig.subplots_adjust(hspace=.4)
ax1 = fig.add_subplot(5,1,1)
ax1.plot(df1['Global_active_power'].resample('D').mean(),linewidth=1)
ax1.set_title('Mean Global active power resampled over day')
ax1.tick_params(axis='both', which='major')

ax2 = fig.add_subplot(5,1,2, sharex=ax1)
ax2.plot(df1['Global_active_power'].resample('W').mean(),linewidth=1)
ax2.set_title('Mean Global active power resampled over week')
ax2.tick_params(axis='both', which='major')

ax3 = fig.add_subplot(5,1,3, sharex=ax1)
ax3.plot(df1['Global_active_power'].resample('M').mean(),linewidth=1)
ax3.set_title('Mean Global active power resampled over month')
ax3.tick_params(axis='both', which='major')

ax4  = fig.add_subplot(5,1,4, sharex=ax1)
ax4.plot(df1['Global_active_power'].resample('Q').mean(),linewidth=1)
ax4.set_title('Mean Global active power resampled over quarter')
ax4.tick_params(axis='both', which='major')

ax5  = fig.add_subplot(5,1,5, sharex=ax1)
ax5.plot(df1['Global_active_power'].resample('A').mean(),linewidth=1)
ax5.set_title('Mean Global active power resampled over year')
ax5.tick_params(axis='both', which='major');
复制代码

図5

一般的には、昇順または降順の傾向は私達の時間に存在しません。最高の平均電力消費量は、2007年であると思われる、実際には、それは我々が2007年にしているので、データのわずか12ヶ月である(翻訳者注:オリジナルは間違っている、それが唯一の12月に2006年のデータでなければなりません)、月中ピーク月です。それは我々が年々比較した場合、実際には、このシーケンスは、比較的安定している、です。

全体の平均有効消費電力図と年に、季節、月、日のパケット

plt.figure(figsize=(14,8))
plt.subplot(2,2,1)
df.groupby('year').Global_active_power.agg('mean').plot()
plt.xlabel('')
plt.title('Mean Global active power by Year')

plt.subplot(2,2,2)
df.groupby('quarter').Global_active_power.agg('mean').plot()
plt.xlabel('')
plt.title('Mean Global active power by Quarter')

plt.subplot(2,2,3)
df.groupby('month').Global_active_power.agg('mean').plot()
plt.xlabel('')
plt.title('Mean Global active power by Month')

plt.subplot(2,2,4)
df.groupby('day').Global_active_power.agg('mean').plot()
plt.xlabel('')
plt.title('Mean Global active power by Day');
复制代码

6

その他の画像は、私たちの以前の知見を確認します。年間ベースでは、シーケンスは比較的安定しています。四半期では、第三四半期で最も低い平均消費電力。月次ベースで、7月と8月で最低の平均消費電力。日では、約8番の最低の月平均消費量(理由はわかりません)。

年間総有効電力

今回は、2006年に削除しました。

pd.pivot_table(df.loc[df['year'] != 2006], values = "Global_active_power",
               columns = "year", index = "month").plot(subplots = True, figsize=(12, 12), layout=(3, 5), sharey=True);
复制代码

図7

2007年から2010年まで、毎年恒例のパターンは非常に似ています。

有効電力の平日と週末の全体的な比較

dic={0:'Weekend',1:'Weekday'}
df['Day'] = df.weekday.map(dic)

a=plt.figure(figsize=(9,4))
plt1=sns.boxplot('year','Global_active_power',hue='Day',width=0.6,fliersize=3,
                    data=df)
a.legend(loc='upper center', bbox_to_anchor=(0.5, 1.00), shadow=True, ncol=2)
sns.despine(left=True, bottom=True)
plt.xlabel('')
plt.tight_layout()
plt.legend().set_visible(False);
复制代码

図8

2010年には、週末より低い平日の全体的なアクティブ中央値。2010年に、彼らは正確に同じです。

図平日と週末全体の能動力率比較

plt1=sns.factorplot('year','Global_active_power',hue='Day',
                    data=df, size=4, aspect=1.5, legend=False)
plt.title('Factor Plot of Global active power by Weekend/Weekday')
plt.tight_layout()
sns.despine(left=True, bottom=True)
plt.legend(loc='upper right');
复制代码

図9

年間ベースでは、平日と週末には同じパターンに従いました。

原則的に、ときLSTMは、我々はテストまたは正しいする必要はありません安定性データが安定している場合は、それが学ぶためにニューラルネットワークを簡単に、モデルのパフォーマンスを向上させることができます。

安定

統計に、ディッキーフラーテストテスト自己回帰モデルにおける単位根があるという帰無仮説。異なる試験方法の使用に基づく代替的な仮説は変化するが、通常は滑らかなまたは安定した傾向

平均と分散静止シリーズは、一定となっています。時間差での時系列は平均値と標準スライディングウィンドウではありません。

ディッキー・フラーテスト

ゼロ検査(H0):時系列は、それが非定常であることを意味し、単位根を示します。これは、食材や時刻関連の数が含まれています。

代替試験(H1)は:それが滑らかであることを意味し、何時系列単位根が存在しないことを示しています。これは、食材や時刻関連が含まれていません。

p値> 0.05:ゼロ試験(H0)、及び非定常部ルートでデータを受信します。

p値<= 0.05:ヌル試験(H0)の拒絶反応は、データは、ルートではなく、ユニットが静止しています。

df2=df1.resample('D', how=np.mean)

def test_stationarity(timeseries):
    rolmean = timeseries.rolling(window=30).mean()
    rolstd = timeseries.rolling(window=30).std()

    plt.figure(figsize=(14,5))
    sns.despine(left=True)
    orig = plt.plot(timeseries, color='blue',label='Original')
    mean = plt.plot(rolmean, color='red', label='Rolling Mean')
    std = plt.plot(rolstd, color='black', label = 'Rolling Std')

    plt.legend(loc='best'); plt.title('Rolling Mean & Standard Deviation')
    plt.show()

    print ('<Results of Dickey-Fuller Test>')
    dftest = adfuller(timeseries, autolag='AIC')
    dfoutput = pd.Series(dftest[0:4],
                         index=['Test Statistic','p-value','#Lags Used','Number of Observations Used'])
    for key,value in dftest[4].items():
        dfoutput['Critical Value (%s)'%key] = value
    print(dfoutput)
test_stationarity(df2.Global_active_power.dropna())
复制代码

10

上記の結果を得ることができるから、そこにはデータ単位根がなく、滑らかであるので、我々は、ヌル試験H0を拒否します。

LSTM

私たちの使命は、予測を行うために、この時系列の200万分の消費の家族歴に基づいています。私たちは、時系列の最終値を予測するために、多層LSTMリカレントニューラルネットワークを使用します。

あなたは計算時間を短縮するために、かつ迅速に結果がモデルをテストする場合は、時間内のデータのサンプリングを再することができます。この記事の実験では、私は、元の分を維持します。

LSTMモデルを構築する前に、以下の作業が前処理および機能データ工学を必要とされます。

  • すべてのデータ型がfloatであることを保証するために、データセットを作成します。
  • 標準化された機能。
  • セグメンテーションのトレーニングとテストセット。
  • データセットの値の配列を変換する行列です。
  • 寸法およびYは、T + 1 = = XにTを変換。
  • 三次元(num_samples、num_timesteps、num_features)に寸法入力。
dataset = df.Global_active_power.values #numpy.ndarray
dataset = dataset.astype('float32')
dataset = np.reshape(dataset, (-1, 1))
scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset)
train_size = int(len(dataset) * 0.80)
test_size = len(dataset) - train_size
train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]

def create_dataset(dataset, look_back=1):
    X, Y = [], []
    for i in range(len(dataset)-look_back-1):
        a = dataset[i:(i+look_back), 0]
        X.append(a)
        Y.append(dataset[i + look_back, 0])
    return np.array(X), np.array(Y)

look_back = 30
X_train, Y_train = create_dataset(train, look_back)
X_test, Y_test = create_dataset(test, look_back)

# 将输入维度转化为 [samples, time steps, features]
X_train = np.reshape(X_train, (X_train.shape[0], 1, X_train.shape[1]))
X_test = np.reshape(X_test, (X_test.shape[0], 1, X_test.shape[1]))
复制代码

モデル構造

  • LSTM定義されたモデル、ニューロンの隠れ層100、Global_active_powerを予測するため、ニューロンを含む出力層を含みます。寸法入力は、30時間の工程を含む機能です。
  • ドロップアウトは20%。
  • 損失の平均二乗誤差を使用して機能、及びアダム確率的勾配降下のより高い効率の向上。
  • モデルは、各バッチのサイズは70で、20のエポックを養成します。
model = Sequential()
model.add(LSTM(100, input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(Dropout(0.2))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')

history = model.fit(X_train, Y_train, epochs=20, batch_size=70, validation_data=(X_test, Y_test),
                    callbacks=[EarlyStopping(monitor='val_loss', patience=10)], verbose=1, shuffle=False)

model.summary()
复制代码

予測を行います

train_predict = model.predict(X_train)
test_predict = model.predict(X_test)
# 预测值求逆
train_predict = scaler.inverse_transform(train_predict)
Y_train = scaler.inverse_transform([Y_train])
test_predict = scaler.inverse_transform(test_predict)
Y_test = scaler.inverse_transform([Y_test])

print('Train Mean Absolute Error:', mean_absolute_error(Y_train[0], train_predict[:,0]))
print('Train Root Mean Squared Error:',np.sqrt(mean_squared_error(Y_train[0], train_predict[:,0])))
print('Test Mean Absolute Error:', mean_absolute_error(Y_test[0], test_predict[:,0]))
print('Test Root Mean Squared Error:',np.sqrt(mean_squared_error(Y_test[0], test_predict[:,0])))
复制代码

損失モデルを描きます

plt.figure(figsize=(8,4))
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Test Loss')
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epochs')
plt.legend(loc='upper right')
plt.show();
复制代码

11

実際の値と予測値の比較

私の結果では、1分間の各時間ステップ。あなたがデータを再サンプリングする前に時間にしている場合は、各時間ステップでの検索結果は1時間です。

私は最近、実際の値と予測値200分を比較します。

aa=[x for x in range(200)]
plt.figure(figsize=(8,4))
plt.plot(aa, Y_test[0][:200], marker='.', label="actual")
plt.plot(aa, test_predict[:,0][:200], 'r', label="prediction")
# plt.tick_params(left=False, labelleft=True) # 移除 ticks
plt.tight_layout()
sns.despine(top=True)
plt.subplots_adjust(left=0.07)
plt.ylabel('Global_active_power', size=15)
plt.xlabel('Time step', size=15)
plt.legend(fontsize=15)
plt.show();
复制代码

12

LSTMs素晴らしいです!

JupyterノートブックはできGithubのがで見つかりました。今週の残りの時間をお楽しみください!

参考:KerasでLSTMsと多変量時系列予測

あなたは、変換エラーや改善のための他の領域がある見つけた場合は、へようこそデンバー翻訳プログラムは変更と翻訳PRは、また、対応するボーナスポイントを得ることができます。記事の冒頭固定リンクの記事は、 GitHubの上で、この記事内のリンク値下げです。


ナゲッツ翻訳プロジェクトは、技術的な記事のインターネットコミュニティの高品質な翻訳のためのソースでナゲッツに英語を共有する記事。カバーのコンテンツのAndroidiOSのフロントエンドバックエンドブロックチェーン製品設計人工知能などの分野は、あなたがより多くの高品質の翻訳を見たいと思って、集中し続ける下さいナゲッツ翻訳プログラムを公式マイクロブログは私たちはほとんどの列を知っています

おすすめ

転載: juejin.im/post/5cecdbb75188252db706f4e9