1. 程式人生 > >Python時間序列LSTM預測系列學習筆記(10)-多步預測

Python時間序列LSTM預測系列學習筆記(10)-多步預測

本文是對:

https://machinelearningmastery.com/multi-step-time-series-forecasting-long-short-term-memory-networks-python/

https://blog.csdn.net/iyangdi/article/details/77881755

博文的學習筆記,博主筆風都很浪,有些細節一筆帶過,本人以謙遜的態度進行了學習和整理,筆記內容都在程式碼的註釋中。有不清楚的可以去原博主文中檢視。

資料集下載:https://datamarket.com/data/set/22r0/sales-of-shampoo-over-a-three-year-period

後期我會補上我的github
 

本文主要是告訴我們一種多步預測的方法。

什麼是多步預測?可以理解為我取最新的3條資料去預測下一條資料,再用最近的2條資料和剛預測出來的1條資料去重新進行預測。

文章中沒有對資料進行正常的預測,只是簡單的把最後一次觀測值作為預測值,演示了一下多步預測的流程,最後算了一下損失函式的數值。

資料上並沒有參考意義,所以最後做出的圖形也沒有參考意義,我們只需理解其思路即可。

本人對文章的批註都載入程式碼的註釋中,文章整理如下:

 

資料準備與模型評估

1、拆分成訓練和測試資料。
訓練資料=前兩年香皂銷售資料
測試資料=剩下一年的香皂銷售資料

2、Multi-Step 預測
假設需要預測3個月的銷售資料

3、模型評估
用rolling-forcast(walk-forward)方式模型驗證
測試資料每個時間步,滑動一個值,預測;之後測試資料的下一個真實觀測值加入模型,並預測

用RMSE評估

持久模型(Persistence Model)

他是很好的時間序列預測的基準
是最簡單的預測

原理:
用當前值作為之後的預測值
 

 

# coding=utf-8
from pandas import read_csv
from pandas import DataFrame
from pandas import concat
from sklearn.metrics import mean_squared_error
from math import sqrt
from matplotlib import pyplot
from pandas import datetime


def parser(x):
    return datetime.strptime(x, '%Y/%m/%d')

# 把資料拆分,線性資料變成四個一組的監督型資料
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
    n_vars = 1 if type(data) is list else data.shape[1]
    df = DataFrame(data)  # 資料多了行標、列標
    cols, names = list(), list()
    for i in range(n_in, 0, -1):
        cols.append(df.shift(i))
        names += [('var%d(t-%d)' % (j + 1, i)) for j in range(n_vars)]
    for i in range(0, n_out, 1):
        cols.append(df.shift(-i))
        if i == 0:
            names += [('var%d(t)' % (j + 1)) for j in range(n_vars)]
        else:
            names += [('var%d(t+%d)' % (j + 1, i)) for j in range(n_vars)]
    agg = concat(cols, axis=1)
    agg.columns = names
    if dropnan:
        agg.dropna(inplace=True)
    return agg


# 拆分正訓練+測試資料
def prepare_data(series, n_test, n_lay, n_seq):
    raw_values = series.values
    raw_values = raw_values.reshape(len(raw_values), 1)
     #轉換成四個一組的監督型資料
    supervised = series_to_supervised(raw_values, n_lay, n_seq)
    supervised_values = supervised.values
    # 前3/4作為訓練資料,後1/4作為預測 測試資料
    train, test = supervised_values[0:-n_test], supervised_values[-n_test:]
    return train, test


# persistence model預測
# 用上一次觀察值作為之後n_seq的預測值
# 其實只是單純的把上一次的觀測值,重複三次寫入一個包含三個元素的陣列,作為一個包含三個元素的預測結果
def persistence(last_ob, n_seq):
    return [last_ob for i in range(n_seq)]


# 評估persistence model
# 把由
def make_forcast(train, test, n_lay, n_seq):
    forcasts = list()
    for i in range(len(test)):
        x, y = test[i, 0:n_lag], test[i, n_lag:]
        # 這裡的預測其實就是抄寫上一次的觀測值,把觀測值變成一個數組列表
        forcast = persistence(x[-1], n_seq)
        forcasts.append(forcast)
    return forcasts


# 預測評估
# 計算預測結果的損失值,把抄寫的觀測值結果帶入運算損失值,輸出。
def evaluate_forcasts(test, forcasts, n_lag, n_seq):
    for i in range(n_seq):
        actual = test[:, (n_lag + i)]
        predicted = [forcast[i] for forcast in forcasts]
        print('predicted')
        print(predicted)
        rmse = sqrt(mean_squared_error(actual, predicted))
        print('t+%d RMSE:%f' % ((i + 1), rmse))  # 1~n_seq各個長度的預測的rmse


def plot_forcasts(series, forcasts, n_test):
    # 原始資料
    pyplot.plot(series.values)
    # 預測資料
    for i in range(len(forcasts)):
        off_s = len(series) - n_test + i - 1
        off_e = off_s + len(forcasts[i]) + 1
        xaxis = [x for x in range(off_s, off_e)]
        yaxis = [series.values[off_s]] + forcasts[i]
        print('xaxis')
        print(xaxis)
        print('yaxis')
        print(yaxis)
        print('series.values[off_s]')
        print(series.values[off_s])
        pyplot.plot(xaxis, yaxis, color='red')
    pyplot.show()


series = read_csv('data_set/shampoo-sales.csv', header=0, parse_dates=[0], index_col=0, squeeze=True, date_parser=parser)

# 一步資料,預測3步
n_lag = 1
n_seq = 3
n_test = 10  # 給了最後12個月,預測3個月,則能預測的次數是10,即10個3個月,即1,2,3->4 2,3,4->5 3,4,5->6 ...
train, test = prepare_data(series, n_test, n_lag, n_seq)
print('train data')
print(train)
print('test data')
print(test)
forecasts = make_forcast(train, test, n_lag, n_seq)
print('forecasts')
print(forecasts)
# 沒有任何意義,只是為了教你如何進行多步的預測,資料全是根據最後觀測值編造的
evaluate_forcasts(test, forecasts, n_lag, n_seq)
plot_forcasts(series, forecasts, n_test + 2)