# -*- 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()
keras实现lstm多变量预测
最新推荐文章于 2024-07-18 08:54:56 发布