1. 程式人生 > >國際旅行人數預測——使用LSTM

國際旅行人數預測——使用LSTM

時間序列問題增加了輸入變數之間的序列依賴性,這樣大大提升了模型的複雜程度。LSTM是迴圈神經網路的一種,可以成功地訓練架構非常複雜的深度學習模型,用於處理時間序列問題。

LSTM對輸入資料的尺度十分敏感,特別是使用sigmoid(這是預設的)或者tanh作為啟用函式的時候。

下面程式碼中使用Scikit-Learn中的MinMaxScaler預處理類對資料集進行歸一化處理,將資料縮放到0——1。

LSTM的輸入資料具有以下形式的特定陣列結構:[樣本,時間步長,特徵]。在create_dataset()函式中生成的資料集採用的是如下的形式:[樣本,特徵]。然後需要使用numpy.reshape()函式對資料集進行結構轉換,轉換時將每個樣本作為一個時間步長。

這裡構建一個具有單個神經元的輸入層、具有4個LSTM儲存單元的隱藏層,以及具有單個值預測的輸出層的神經網路。LSTM儲存單元採用的是預設的sigmoid啟用函式。對網路訓練100個epochs,並將batch_size設定為1。

例子來源於魏貞原老師的深度學習書籍。

"""
LSTM時間序列問題預測:國際旅行人數預測
"""
import numpy as np
from matplotlib import pyplot as plt
from pandas import read_csv
import math
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error

seed = 7
batch_size = 1
epochs = 100
filename = 'F:/Python/pycharm/keras_deeplearning/datasets/international-airline-passengers.csv'
footer = 3
look_back = 1

def create_dataset(dataset):
    #建立資料集
    dataX, dataY = [],[]
    for i in range(len(dataset) - look_back - 1):
        x= dataset[i:i+look_back, 0]
        dataX.append(x)
        y = dataset[i+look_back, 0]
        dataY.append(y)
        print('X: %s, Y: %s' % (x,y))
    return np.array(dataX), np.array(dataY)

def build_model():
    model = Sequential()
    model.add(LSTM(units=4, input_shape=(1, look_back)))
    model.add(Dense(units=1))
    model.compile(loss='mean_squared_error', optimizer='adam')
    return model

if __name__ == '__main__':
    #設定隨機種子
    np.random.seed(seed)

    #匯入資料
    data = read_csv(filename, usecols=[1], engine='python', skipfooter=footer)
    dataset = data.values.astype('float32')
    #標準化資料
    scaler = MinMaxScaler()
    dataset = scaler.fit_transform(dataset)
    train_size = int(len(dataset) * 0.67)
    validation_size = len(dataset) - train_size
    train, validation = dataset[0:train_size, :], dataset[train_size:len(dataset), :]

    #建立dataset,使資料產生相關性
    X_train, y_train = create_dataset(train)
    X_validation, y_validation = create_dataset(validation)
    #將資料轉換成[樣本,時間步長,特徵]的形式
    X_train = np.reshape(X_train, (X_train.shape[0], 1, X_train.shape[1]))
    X_validation = np.reshape(X_validation, (X_validation.shape[0], 1, X_validation.shape[1]))

    #訓練模型
    model = build_model()
    model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, verbose=2)

    #模型預測資料
    predict_train = model.predict(X_train)
    predict_validation = model.predict(X_validation)

    #反標準化資料,目的是為了保證MSE的準確性
    predict_train = scaler.inverse_transform(predict_train)
    y_train = scaler.inverse_transform([y_train])
    predict_validation = scaler.inverse_transform(predict_validation)
    y_validation = scaler.inverse_transform([y_validation])

    #評估模型
    train_score = math.sqrt(mean_squared_error(y_train[0], predict_train[:, 0]))
    print('Train Score: %.2f RMSE' % train_score)
    validation_score = math.sqrt(mean_squared_error(y_validation[0], predict_validation[:, 0]))
    print('Validation Score : %.2f RMSE' % validation_score)

    #構建通過訓練資料集進行預測的圖表資料
    predict_train_plot = np.empty_like(dataset)
    predict_train_plot[:, :] = np.nan
    predict_train_plot[look_back:len(predict_train) + look_back, :] = predict_train

    # 構建通過評估資料集進行預測的圖表資料
    predict_validation_plot = np.empty_like(dataset)
    predict_validation_plot[:, :] = np.nan
    predict_validation_plot[len(predict_train) + look_back * 2 + 1 : len(dataset) - 1, :] = predict_validation

    #圖表顯示
    dataset = scaler.inverse_transform(dataset)
    plt.plot(dataset, color='black')
    plt.plot(predict_train_plot, color='green')
    plt.plot(predict_validation_plot, color='red')
    plt.show()

輸出結果為:

Train Score: 22.65 RMSE
Validation Score : 48.57 RMSE