LSTM时间序列预测及网络层搭建
最近看到一篇博客,是時間預測問題,數據和代碼的原地址在這里,
https://www.jianshu.com/p/5d6d5aac4dbd
下面只是對其復現和思考:
首先關于數據預處理的問題,大家可以參考:https://blog.csdn.net/lilong117194/article/details/82911073
1. LSTM預測未來一年某航空公司的客運流量
這里的問題是:給你一個數據集,只有一列數據,這是一個關于時間序列的數據,從這個時間序列中預測未來一年某航空公司的客運流量。
數據形式:
下面的代碼主要分為以下幾步:
數據預處理這塊參考上面的鏈接就可以,而模型的搭建是基于keras的模型,稍微有點疑惑的地方就是數據的構建(訓練集和測試集),還有數據的預處理方法的問題。
# -*- coding: utf-8 -*-import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import MinMaxScaler from keras.models import Sequential from keras.layers import LSTM, Dense, Activationdef load_data(file_name, sequence_length=10, split=0.8):# 提取數據一列df = pd.read_csv(file_name, sep=',', usecols=[1])# 把數據轉換為數組data_all = np.array(df).astype(float)# 將數據縮放至給定的最小值與最大值之間,這里是0與1之間,數據預處理scaler = MinMaxScaler()data_all = scaler.fit_transform(data_all)print(len(data_all)) data = []# 構造送入lstm的3D數據:(133, 11, 1)for i in range(len(data_all) - sequence_length - 1):data.append(data_all[i: i + sequence_length + 1])reshaped_data = np.array(data).astype('float64')print(reshaped_data.shape)# 打亂第一維的數據np.random.shuffle(reshaped_data)print('reshaped_data:',reshaped_data[0])# 這里對133組數據進行處理,每組11個數據中的前10個作為樣本集:(133, 10, 1)x = reshaped_data[:, :-1]print('samples:',x.shape)# 133組樣本中的每11個數據中的第11個作為樣本標簽y = reshaped_data[:, -1]print('labels:',y.shape)# 構建訓練集(訓練集占了80%)split_boundary = int(reshaped_data.shape[0] * split)train_x = x[: split_boundary]# 構建測試集(原數據的后20%)test_x = x[split_boundary:]# 訓練集標簽train_y = y[: split_boundary]# 測試集標簽test_y = y[split_boundary:]# 返回處理好的數據return train_x, train_y, test_x, test_y, scaler# 模型建立 def build_model():# input_dim是輸入的train_x的最后一個維度,train_x的維度為(n_samples, time_steps, input_dim)model = Sequential()model.add(LSTM(input_dim=1, output_dim=50, return_sequences=True))print(model.layers)model.add(LSTM(100, return_sequences=False))model.add(Dense(output_dim=1))model.add(Activation('linear'))model.compile(loss='mse', optimizer='rmsprop')return modeldef train_model(train_x, train_y, test_x, test_y):model = build_model()try:model.fit(train_x, train_y, batch_size=512, nb_epoch=30, validation_split=0.1)predict = model.predict(test_x)predict = np.reshape(predict, (predict.size, ))except KeyboardInterrupt:print(predict)print(test_y)print('predict:\n',predict)print('test_y:\n',test_y)# 預測的散點值和真實的散點值畫圖try:fig1 = plt.figure(1)plt.plot(predict, 'r:')plt.plot(test_y, 'g-')plt.legend(['predict', 'true'])except Exception as e:print(e)return predict, test_yif __name__ == '__main__':# 加載數據train_x, train_y, test_x, test_y, scaler = load_data('international-airline-passengers.csv') 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))# 模型訓練 predict_y, test_y = train_model(train_x, train_y, test_x, test_y)# 對標準化處理后的數據還原predict_y = scaler.inverse_transform([[i] for i in predict_y])test_y = scaler.inverse_transform(test_y)# 把預測和真實數據對比fig2 = plt.figure(2)plt.plot(predict_y, 'g:')plt.plot(test_y, 'r-')plt.legend(['predict', 'true'])plt.show()運行結果:
從結果可以看出預測效果還可以,但是理論上存在諸多問題:
基于以上的主要問題,在完全沒有未來數據參與下進行訓練,進行修改后的數據處理過程如下:全集—分割—訓練集歸一訓練—驗證集使用訓練集std&mean進行歸一完成預測。
這里就是先試下沒有打亂數據的情況,就是按照順序的數據集構建進行訓練和預測:
#!/usr/bin/env python3 # -*- coding: utf-8 -*-import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import MinMaxScaler from keras.models import Sequential from keras.layers import LSTM, Dense, Activation# 數據集的構建 def dataset_func(data_pro,sequence_length=10):data = []# 構造數據集:構造送入lstm的3D數據for i in range(len(data_pro) - sequence_length - 1):data.append(data_pro[i: i + sequence_length + 1])reshaped_data = np.array(data).astype('float64')print('here:',reshaped_data.shape)# 打亂數據集#np.random.shuffle(reshaped_data)print('reshaped_data:',reshaped_data[0])# 數據集的特征和標簽分開:樣本中的每11個數據中的第11個作為樣本標簽x = reshaped_data[:, :-1]print('samples:',x.shape)y = reshaped_data[:, -1]print('labels:',y.shape)return x,ydef load_data(file_name, sequence_length=10, split=0.8):# 提取數據一列df = pd.read_csv(file_name, sep=',', usecols=[1])# 把數據轉換為數組data_all = np.array(df).astype(float)print('length of data_all:',data_all.shape)# 全集劃分:80%的訓練數據split_boundary = int(data_all.shape[0] * split)print(split_boundary)train_x = data_all[: split_boundary]print(train_x.shape)# 訓練集的歸一化:將數據縮放至給定的最小值與最大值之間,這里是0與1之間,數據預處理scaler = MinMaxScaler()data_train = scaler.fit_transform(train_x)print('length:',len(data_train)) train_x,train_y=dataset_func(data_train,sequence_length=10)# 全集劃分:20%的驗證數據test_x = data_all[split_boundary:]print(test_x.shape)data_test = scaler.transform(test_x)print('length:',len(data_test)) test_x,test_y=dataset_func(data_test,sequence_length=10)# 返回處理好的數據return train_x, train_y, test_x, test_y, scaler# 模型建立 def build_model():# input_dim是輸入的train_x的最后一個維度,train_x的維度為(n_samples, time_steps, input_dim)model = Sequential()model.add(LSTM(input_dim=1, output_dim=50, return_sequences=True))print(model.layers)model.add(LSTM(100, return_sequences=False))model.add(Dense(output_dim=1))model.add(Activation('linear'))model.compile(loss='mse', optimizer='rmsprop')return modeldef train_model(train_x, train_y, test_x, test_y):model = build_model()try:model.fit(train_x, train_y, batch_size=512, nb_epoch=30, validation_split=0.1)predict = model.predict(test_x)predict = np.reshape(predict, (predict.size, ))except KeyboardInterrupt:print(predict)print(test_y)print('predict:\n',predict)print('test_y:\n',test_y)# 預測的散點值和真實的散點值畫圖try:fig1 = plt.figure(1)plt.plot(predict, 'r:')plt.plot(test_y, 'g-')plt.legend(['predict', 'true'])except Exception as e:print(e)return predict, test_yif __name__ == '__main__':# 加載數據train_x, train_y, test_x, test_y, scaler = load_data('international-airline-passengers.csv') 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))# 模型訓練 predict_y, test_y = train_model(train_x, train_y, test_x, test_y)# 對標準化處理后的數據還原predict_y = scaler.inverse_transform([[i] for i in predict_y])test_y = scaler.inverse_transform(test_y)# 把預測和真實數據對比fig2 = plt.figure(2)plt.plot(predict_y, 'g:')plt.plot(test_y, 'r-')plt.legend(['predict', 'true'])plt.show()主要就是數據的構建改變了,運行結果如下:
可以看出效果很差,具體為什么按照常規的順序數據構建(不打亂)預測效果那么差,還在思考中。。。。
下面又嘗試了:全集—分割—訓練集歸一shuffle并記錄std&mean—訓練—驗證集使用訓練集std&mean進行歸一完成預測。
僅僅把上面代碼中數據順序打亂的注釋去掉就可以了:
#np.random.shuffle(reshaped_data)
再次訓練得到:
效果還是不理想,所以這里僅僅作為學習的過程,以后再研究。
2. keras的lstm層函數
keras.layers.recurrent.LSTM(units, activation='tanh', recurrent_activation='hard_sigmoid', use_bias=True, kernel_initializer='glorot_uniform', recurrent_initializer='orthogonal', bias_initializer='zeros', unit_forget_bias=True, kernel_regularizer=None, recurrent_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, recurrent_constraint=None, bias_constraint=None, dropout=0.0, recurrent_dropout=0.0)
2.1 參數說明:
- units:輸出維度
- input_dim:輸入維度,當使用該層為模型首層時,應指定該值(或等價的指定input_shape)
- return_sequences:布爾值,默認False,控制返回類型。若為True則返回整個序列,否則僅返回輸出序列的最后一個輸出
- input_length:當輸入序列的長度固定時,該參數為輸入序列的長度。當需要在該層后連接Flatten層,然后又要連接Dense層時,需要指定該參數,否則全連接的輸出無法計算出來。
2.2 輸入shape :
形如(samples,timesteps,input_dim)的3D張量
2.3 輸出shape:
如果return_sequences=True:返回形如(samples,timesteps,output_dim)的3D張量,否則返回形如(samples,output_dim)的2D張量。
2.4 輸入和輸出的類型 :
相對之前的tensor,這里多了個參數timesteps,其表示什么意思?假如我們輸入有100個句子,每個句子都由5個單詞組成,而每個單詞用64維的詞向量表示。那么samples=100,timesteps=5,input_dim=64,可以簡單地理解timesteps就是輸入序列的長度input_length(視情而定)
2.5 units :
假如units=128,就一個單詞而言,你可以把LSTM內部簡化看成 :
Y=X1×64W64×128Y=X_{1×64}W_{64×128}Y=X1×64?W64×128?,X為上面提及的詞向量比如64維,W中的128就是units,也就是說通過LSTM,把詞的維度由64轉變成了128
2.6 return_sequences
我們可以把很多LSTM層串在一起,但是最后一個LSTM層return_sequences通常為false,具體看下面的例子:
句子:you are really a genius
(1)我們把輸入的單詞,轉換為維度64的詞向量,最下面一層的小矩形的數目即單詞的個數input_length(每個句子的單詞個數)。
(2)通過第一個LSTM中的Y=XW,這里輸入為維度64,輸出為維度128,而return_sequences=True,我們可以獲得5個128維的詞向量V1′,V2...V5′V1',V2...V5'V1′,V2...V5′
(3)通過第二個LSTM(這里上圖沒有顯示出來,最上面應該還有一層),此時輸入為V1′,V2...V5′V1',V2...V5'V1′,V2...V5′都為128維,經轉換后得到V1′′,V2′′,...V5′′V1'',V2'',...V5''V1′′,V2′′,...V5′′為256維,最后因為return_sequences=False,所以只輸出了最后一個紅色的詞向量。
下面是一個動態圖,有助于理解:
2.7 在實際應用中,有如下的表示形式:
參考:
https://www.zhihu.com/question/41949741?sort=created
https://blog.csdn.net/jiangpeng59/article/details/77646186
總結
以上是生活随笔為你收集整理的LSTM时间序列预测及网络层搭建的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三蒸三晒红枣吃了有什么好处?
- 下一篇: 2022怎么装修最省钱实用8个装修省钱大