LSTM原理及python简易实现

LSTM原理及python简易实现

https://www.jianshu.com/p/daedde46eae5

例子:

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.preprocessing import LabelEncoder
from sklearn.metrics import mean_squared_error
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
import pandas as pd

"""
本文是LSTM多元预测
用3个步长的数据预测1个步长的数据
包含:
对数据进行缩放,缩放格式为n行*8列,因为数据没有季节性,所以不做差分
对枚举列(风向)进行数字编码
构造3->1的监督学习数据
构造网络开始预测
将预测结果重新拼接为n行*8列数据
数据逆缩放,求RSME误差
"""
pd.set_option('display.max_columns',1000)
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth',1000)

# 转换成监督数据,四列数据,3->1,三组预测一组
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):    #输入n_in=3  ,  输出 n_out=1  (前3小时预测后1小时)
    n_vars = 1 if type(data) is list else data.shape[1]  #相当于java里的三目运算符   z=x>y?x-y:x+y   #此处data.shape=(43800, 8),故 n_vars=8
    df = DataFrame(data)  #DataFrame为表格型数据结构 https://www.jianshu.com/p/8024ceef4fe2
    cols, names = list(), list()   #创建空表
    # input sequence (t-n, ... t-1)
    # 将3组输入数据依次向下移动3,2,1行,将数据加入cols列表(技巧:(n_in, 0, -1)中的-1指倒序循环,步长为1)
    for i in range(n_in, 0, -1):  #n_in=3
    	cols.append(df.shift(i))     #shift(i)往下移动i行
    	names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
    # forecast sequence (t, t+1, ... t+n)
    # 将一组输出数据加入cols列表(技巧:其中i=0)
    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)]
    # cols列表(list)中现在有四块经过下移后的数据(即:df(-3),df(-2),df(-1),df),将四块数据按列 并排合并
    agg = concat(cols, axis=1)
    # 给合并后的数据添加列名
    agg.columns = names
    print(agg)
    # 删除NaN值列
    if dropnan:
    	agg.dropna(inplace=True)
    return agg

# load dataset
dataset = read_csv('pollution.csv', header=0, index_col=0)   #以第0列当索引
print(dataset.head(10))        #打印前10行
print(dataset.shape)           #默认不包含表头
values = dataset.values        #取除去横、纵表头的所有值赋给values
print(values[0])      #values不属于DataFrames类型
print(values.shape)
# 对“风向”列进行整数编码  ,随便返回一个整型数
encoder = LabelEncoder()
values[:,4] = encoder.fit_transform(values[:,4])
for i in range(0,10):
    print(values[i])
values = values.astype('float32')

# 标准化/放缩 特征值在(0,1)之间
scaler = MinMaxScaler(feature_range=(0, 1))  #每一列归一化(0,1),不同属性互不干扰
scaled = scaler.fit_transform(values)

for i in range(0,10):
    print(scaled[i])
# 用3小时数据预测一小时数据,8个特征值
n_hours = 3
n_features = 8
# 构造一个3->1的监督学习型数据



reframed = series_to_supervised(scaled, n_hours, 1)     #构造输入输出之后的表
print(reframed.shape)
print(reframed.head(10))




# split into train and test sets
values = reframed.values
# 用2年的数据来训练
n_train_hours = 2*365 * 24   #每行1小时
train = values[:n_train_hours, :]
test = values[n_train_hours:, :]   #之后的数据作测试
# split into input and outputs
n_obs = n_hours * n_features    # 24
# 有32=(4*8)列数据,取前24=(3*8) 列作为X,倒数第8列=(第25列)作为Y
train_X, train_y = train[:, :n_obs], train[:, -n_features]   #前24列作输入 第25列(pollution)作输出(标签)
test_X, test_y = test[:, :n_obs], test[:, -n_features]
print(train_X.shape, len(train_X), train_y.shape)   # (8760=365*24, 24) 8760  (8760,1)
# 将数据转换为3D输入,timesteps=3,3条数据预测1条 [samples, timesteps, features]
train_X = train_X.reshape((train_X.shape[0], n_hours, n_features))  #将(8760, 24)的数据转为(8760,3,8)
test_X = test_X.reshape((test_X.shape[0], n_hours, n_features))
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)    #(8760, 3, 8) (8760,)  (35037, 3, 8) (35037,)

# 设计网络
model = Sequential()
model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2]))) #输入三个
model.add(Dense(1))                                                        #输出1个
model.compile(loss='mae', optimizer='adam')
# 拟合网络
history = model.fit(train_X, train_y, epochs=100, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)   #训练网络并返回一个History对象,该对象包含epoch和history属性
# plot history
model.summary()
pyplot.plot(history.history['loss'], label='train')    #history属性为字典类型,包含val_loss,val_acc,loss,acc四个key值
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],24)
a,b=list(),list()
for i in range(10):
    a.append(test_X[i+3][0])   #污染的真实值
print(yhat.shape)
for i in range(10):
    b.append(yhat[i])          #预测值
c={'real':a,'predict':b}
print(DataFrame(c))
###


# 将数据格式化成 n行 * 24列
test_X = test_X.reshape((test_X.shape[0], n_hours*n_features))
# 将预测列据和后7列数据拼接,因后续逆缩放时,数据形状要符合 n行*8列 的要求
inv_yhat = concatenate((yhat, test_X[:, -7:]), axis=1)
# 对拼接好的数据进行逆缩放
inv_yhat = scaler.inverse_transform(inv_yhat)
inv_yhat = inv_yhat[:,0]

test_y = test_y.reshape((len(test_y), 1))
# 将真实列据和后7列数据拼接,因后续逆缩放时,数据形状要符合 n行*8列 的要求
inv_y = concatenate((test_y, test_X[:, -7:]), axis=1)
# 对拼接好的数据进行逆缩放
inv_y = scaler.inverse_transform(inv_y)
inv_y = inv_y[:,0]

# 计算RMSE误差值
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
print('Test RMSE: %.3f' % rmse)


在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值