浅谈归一化对于LSTM进行时间序列预测的影响(附归一化代码)

首先介绍一下我们的示例数据,此数据是1949 到 1960 一共 12 年,每年 12 个月的航班乘客数据,一共 144 个数据,单位是 1000。
下载地址
或者:百度云链接:https://pan.baidu.com/s/1jIAVEVkcpD2o3pUOfstthQ
提取码:1qn2
数据如图所示
在这里插入图片描述
我们选取前60%作为训练数据,后40%作为测试数据

#头文件
import numpy as np
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
import  pandas as pd
import  os
from keras.models import Sequential, load_model

#加载数据
alldata = pd.read_csv("./international-airline-passengers.csv")
#只取数值列
alldata = alldata.iloc[:,1]
alldata = np.array(alldata,dtype='float64')
traindata = alldata[:int(len(alldata)*0.6)]
testdata = alldata[int(len(alldata)*0.6):]

LSTM进行预测的时候要对于数据进行转换,具体可以见我之前的博客
简单粗暴LSTM:LSTM进行时间序列预测
实验中所用到的函数

#转换函数
def Create_dataset(dataset,look_back):
    data_X, data_Y = [], []
    for i in range(len(dataset) - look_back - 1):
        a = dataset[i:(i + look_back)]
        data_X.append(a)
        data_Y.append(dataset[i + look_back])
    data_X = np.array(data_X)
    data_Y = np.array(data_Y)
    return  data_X,data_Y
    
#单维最大最小归一化和反归一化函数
def Normalize(list):
    list = np.array(list)
    low, high = np.percentile(list, [0, 100])
    delta = high - low
    if delta != 0:
        for i in range(0, len(list)):
            list[i] = (list[i]-low)/delta
    return  list,low,high

def FNoramlize(list,low,high):
    delta = high - low
    if delta != 0:
        for i in range(0, len(list)):
            list[i] = list[i]*delta + low
    return list

#LSTM进行训练的函数
def Train_Model(train_X,train_Y):
    model = Sequential()
    model.add(LSTM(4, input_shape=(train_X.shape[1],train_X.shape[2])))
    #Dense层的1是预测维度为1
    model.add(Dense(1))
    model.compile(loss='mean_squared_error', optimizer='adam')
    model.fit(train_X, train_Y, epochs=1000, batch_size=1, verbose=2)
    # model.save(os.path.join("DATA","LSTMBLog" + ".h5"))
    return model

进行预测实验

实验分为三种情况:
1.对于训练数据和测试数据分别进行归一化
2.对于训练数据进行归一化之后。使用训练数据的最大最小值(训练数据的范围)对于测试数据进行归一化
3.对于训练和测试的整体数据统一进行归一化

1.对于训练数据和测试数据分别进行归一化

#实验1
train_n,train_low,train_high = Normalize(traindata)
test_n,test_low,test_high = Normalize(testdata)
print(train_n,test_n)
#前一个值预测后一个值
train_X,train_Y = Create_dataset(train_n,look_back=1)
test_X,test_Y = Create_dataset(test_n,look_back=1)
#额外添加一个维度使train_X,test_X变为三维
train_X = np.reshape(train_X, (train_X.shape[0], train_X.shape[1], 1))
test_X = np.reshape(test_X, (test_X.shape[0], test_X.shape[1], 1))

model = Train_Model(train_X,train_Y)

train_predict = model.predict(train_X)
test_predict  = model.predict(test_X)

#反归一化
train_Y = FNoramlize(train_Y,train_low,train_high)
train_predict = FNoramlize(train_predict,train_low,train_high)
test_Y = FNoramlize(test_Y,test_low,test_high)
test_predict = FNoramlize(test_predict,test_low,test_high)

#进行绘图
plt.subplot(121)
plt.plot(train_Y)
plt.plot(train_predict)
plt.subplot(122)
plt.plot(test_Y)
plt.plot(test_predict)
plt.show()

结果如图所示:可以看到LSTM对于训练数据和预测数据都能很好的拟合
在这里插入图片描述

2.对于训练数据进行归一化之后。使用训练数据的最大最小值(训练数据的范围)对于测试数据进行归一化

引入新的归一化函数

def Normalize2(list,low,high):
    list = np.array(list)
    delta = high - low
    if delta != 0:
        for i in range(0, len(list)):
            list[i] = (list[i]-low)/delta
    return  list

进行实验

#实验2
train_n,train_low,train_high = Normalize(traindata)
#更新的归一化
test_n = Normalize2(testdata,train_low,train_high)
print(train_n,test_n)
#前一个值预测后一个值
train_X,train_Y = Create_dataset(train_n,look_back=1)
test_X,test_Y = Create_dataset(test_n,look_back=1)
#额外添加一个维度使train_X,test_X变为三维
train_X = np.reshape(train_X, (train_X.shape[0], train_X.shape[1], 1))
test_X = np.reshape(test_X, (test_X.shape[0], test_X.shape[1], 1))

model = Train_Model(train_X,train_Y)

train_predict = model.predict(train_X)
test_predict  = model.predict(test_X)

#反归一化
train_Y = FNoramlize(train_Y,train_low,train_high)
train_predict = FNoramlize(train_predict,train_low,train_high)
test_Y = FNoramlize(test_Y,train_low,train_high)
test_predict = FNoramlize(test_predict,train_low,train_high)

#进行绘图
plt.subplot(121)
plt.plot(train_Y)
plt.plot(train_predict)
plt.subplot(122)
plt.plot(test_Y)
plt.plot(test_predict)
plt.show()

这时预测结果如图
在这里插入图片描述
可以看到对于test数据预测结果发生了变化,周期没有改变,但是值发生了改变

3.对于训练和测试的整体数据统一进行归一化

#实验3
alldata_n,all_low,all_high = Normalize(alldata)
#也可以直接对alldata进行截取
train_n = Normalize2(traindata,all_low,all_high)
test_n = Normalize2(testdata,all_low,all_high)
print(train_n,test_n)

#前一个值预测后一个值
train_X,train_Y = Create_dataset(train_n,look_back=1)
test_X,test_Y = Create_dataset(test_n,look_back=1)
#额外添加一个维度使train_X,test_X变为三维
train_X = np.reshape(train_X, (train_X.shape[0], train_X.shape[1], 1))
test_X = np.reshape(test_X, (test_X.shape[0], test_X.shape[1], 1))

model = Train_Model(train_X,train_Y)

train_predict = model.predict(train_X)
test_predict  = model.predict(test_X)

#反归一化
train_Y = FNoramlize(train_Y,all_low,all_high)
train_predict = FNoramlize(train_predict,all_low,all_high)
test_Y = FNoramlize(test_Y,all_low,all_high)
test_predict = FNoramlize(test_predict,all_low,all_high)

#进行绘图
plt.subplot(121)
plt.plot(train_Y)
plt.plot(train_predict)
plt.subplot(122)
plt.plot(test_Y)
plt.plot(test_predict)
plt.show()

预测结果:
在这里插入图片描述


结论

可以看到LSTM进行预测的时候会保留趋势(周期)信息以及训练数据的高低(范围)信息。
其中
1.对于训练数据和测试数据分别进行归一化 保留周期信息
2.对于训练数据进行归一化之后。使用训练数据的最大最小值(训练数据的范围)对于测试数据进行归一化 保留周期和范围信息
3.对于训练和测试的整体数据统一进行归一化 保留周期和范围信息

在进行LSTM预测的时候,我们可以通过对于归一化的选择来进行是否进行高低信息的使用。

注:代码已上传到我的github,同时附录了单维多维归一化函数
本次实验中2.3.的预测结果也有一些区别,实验中3.的test预测结果更高一些

#这两种方式会产生不同的结果
normalize = np.arange(10,dtype='float64')
normalize = np.arange(10)
normalize.dtype = 'float64'
  • 28
    点赞
  • 197
    收藏
    觉得还不错? 一键收藏
  • 26
    评论
Keras是一个高级神经网络API,它可以在TensorFlow、CNTK或Theano等后端上运行。LSTM是一种递归神经网络,它可以处理时间序列数据。在Keras中,我们可以使用LSTM层来构建时间序列预测模型。 归一化和反归一化是为了将数据缩放到一个特定的范围内,以便于神经网络的训练和预测。在时间序列预测中,我们通常使用MinMaxScaler来进行归一化和反归一化。 以下是一个简单的Keras LSTM时间序列预测模型的代码示例,包括归一化和反归一化代码: ```python import numpy as np from sklearn.preprocessing import MinMaxScaler from keras.models import Sequential from keras.layers import Dense, LSTM # 生成时间序列数据 data = np.array([i*np.sin(i/10) for i in range(100)]) # 归一化数据 scaler = MinMaxScaler(feature_range=(0, 1)) data = scaler.fit_transform(data.reshape(-1, 1)) # 将数据转换为监督学习问题 def create_dataset(data, look_back=1): X, Y = [], [] for i in range(len(data)-look_back): X.append(data[i:i+look_back, 0]) Y.append(data[i+look_back, 0]) return np.array(X), np.array(Y) look_back = 5 X, Y = create_dataset(data, look_back) # 将数据分为训练集和测试集 train_size = int(len(X) * 0.7) test_size = len(X) - train_size X_train, X_test = X[:train_size], X[train_size:] Y_train, Y_test = Y[:train_size], Y[train_size:] # 将数据转换为LSTM的输入格式 X_train = np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1)) X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1)) # 构建LSTM模型 model = Sequential() model.add(LSTM(50, input_shape=(look_back, 1))) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') model.fit(X_train, Y_train, epochs=100, batch_size=1, verbose=2) # 使用模型进行预测 train_predict = model.predict(X_train) test_predict = model.predict(X_test) # 反归一化数据 train_predict = scaler.inverse_transform(train_predict) Y_train = scaler.inverse_transform([Y_train]) test_predict = scaler.inverse_transform(test_predict) Y_test = scaler.inverse_transform([Y_test]) # 输出预测结果 print('Train Mean Squared Error:', np.mean((Y_train[0] - train_predict[:,0])**2)) print('Test Mean Squared Error:', np.mean((Y_test[0] - test_predict[:,0])**2)) # 相关问题: # 1. 什么是时间序列预测? # 2. 什么是LSTM? # 3. 归一化和反归一化的作用是什么?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值