keras实现lstm多变量预测

# -*- coding: utf-8 -*-
"""
Created on Mon Apr 23 11:27:31 2018

@author: Administrator
"""

import matplotlib.pyplot as plt
from math import sqrt
from numpy import concatenate
from matplotlib import pyplot
from pandas import read_csv
from pandas import DataFrame
from pandas import concat
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM

'''
 时间序列预测设备剩余时间:
     根据当前数据的特征与剩余时间预测下一条数据的剩余时间;
     此方法在实际中并不适用,因当前数据的剩余时间也是预测得到,可更改为根据当前数据预测当前剩余时间。
'''

# 组合数据t-n, ... t-1, t, t+1, ... t+n, 默认 t-1,t
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()
	# 输入序列 (t-n, ... t-1)
	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)]
	# 预测序列 (t, t+1, ... t+n)
	for i in range(0, n_out):
		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

# 读取文件,包含头信息
dataset = read_csv('scdata02.csv')
# 删掉不用的字段
dataset = dataset.drop('jh',axis=1)
# df转array
values = dataset.values
# 原始数据标准化
scaler = MinMaxScaler(feature_range=(0, 1))
scaled = scaler.fit_transform(values)
# 根据过去一小时预测当前
n_hours = 1
n_features = scaled.shape[1]
# 构造特征,过去三小时与当前数据集合
reframed = series_to_supervised(scaled, n_hours, 1)
values = reframed.values
# 划分训练集与测试集
size = 0.8
num  = int(values.shape[0]*size)
train = values[:num, :]
test = values[num:, :]
train_X, train_y = train[:, :n_features*n_hours], train[:, -1]
test_X, test_y = test[:, :n_features*n_hours], test[:, -1]
# reshape为 3D [samples, timesteps, features],将n_hours看成n个独立的时间序列而不是一个整体的
train_X = train_X.reshape((train_X.shape[0], n_hours, n_features))
test_X = test_X.reshape((test_X.shape[0], n_hours, n_features))
# 神经网络
model = Sequential()
#输入层有 1 个input,隐藏层有50个神经元
model.add(LSTM(32, input_shape=(train_X.shape[1], train_X.shape[2])))
#输出层就是预测一个值
model.add(Dense(1))
model.compile(loss='mae', optimizer='adam')
# 训练
history = model.fit(train_X, train_y, epochs=500, batch_size=1, validation_data=(test_X, test_y), verbose=2, shuffle=False)
# loss曲线
pyplot.plot(history.history['loss'], label='train')
pyplot.plot(history.history['val_loss'], label='test')
pyplot.legend()
pyplot.show()
# 预测
yhat = model.predict(test_X)
test_X = test_X.reshape((test_X.shape[0], n_hours*n_features))
# 将预测y与当前时间的x组合
inv_yhat0 = concatenate((test_X[:, -n_features:-1], yhat), axis=1)
inv_yhat1 = scaler.inverse_transform(inv_yhat0)
inv_yhat = inv_yhat1[:,-1]
# 将实际y与当前时间的x组合
test_y = test_y.reshape((len(test_y), 1))
inv_y0 = concatenate((test_X[:, -n_features:-1],test_y), axis=1)
inv_y1 = scaler.inverse_transform(inv_y0)
inv_y = inv_y1[:,-1]
# 计算 RMSE
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
print('Test RMSE: %.3f' % rmse)
plt.plot(inv_y)
plt.plot(inv_yhat)
plt.show()

猜你喜欢

转载自blog.csdn.net/ukakasu/article/details/80051537