# 国际旅行人数预测——使用LSTM

LSTM对输入数据的尺度十分敏感，特别是使用sigmoid（这是默认的）或者tanh作为激活函数的时候。

LSTM的输入数据具有以下形式的特定阵列结构：[样本，时间步长，特征]。在create_dataset()函数中生成的数据集采用的是如下的形式：[样本，特征]。然后需要使用numpy.reshape()函数对数据集进行结构转换，转换时将每个样本作为一个时间步长。

"""
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()
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