十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
這篇文章主要為大家展示了“Python中如何使用LSTM模型進(jìn)行時間序列預(yù)測分析”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Python中如何使用LSTM模型進(jìn)行時間序列預(yù)測分析”這篇文章吧。
時間序列模型
時間序列預(yù)測分析就是利用過去一段時間內(nèi)某事件時間的特征來預(yù)測未來一段時間內(nèi)該事件的特征。這是一類相對比較復(fù)雜的預(yù)測建模問題,和回歸分析模型的預(yù)測不同,時間序列模型是依賴于事件發(fā)生的先后順序的,同樣大小的值改變順序后輸入模型產(chǎn)生的結(jié)果是不同的。
舉個栗子:根據(jù)過去兩年某股票的每天的股價數(shù)據(jù)推測之后一周的股價變化;根據(jù)過去2年某店鋪每周想消費(fèi)人數(shù)預(yù)測下周來店消費(fèi)的人數(shù)等等
RNN 和 LSTM 模型
時間序列模型最常用最強(qiáng)大的的工具就是遞歸神經(jīng)網(wǎng)絡(luò)(recurrent neural network, RNN)。相比與普通神經(jīng)網(wǎng)絡(luò)的各計算結(jié)果之間相互獨(dú)立的特點(diǎn),RNN的每一次隱含層的計算結(jié)果都與當(dāng)前輸入以及上一次的隱含層結(jié)果相關(guān)。通過這種方法,RNN的計算結(jié)果便具備了記憶之前幾次結(jié)果的特點(diǎn)。
典型的RNN網(wǎng)路結(jié)構(gòu)如下:
右側(cè)為計算時便于理解記憶而產(chǎn)開的結(jié)構(gòu)。簡單說,x為輸入層,o為輸出層,s為隱含層,而t指第幾次的計算;V,W,U為權(quán)重,其中計算第t次的隱含層狀態(tài)時為St = f(U*Xt + W*St-1),實(shí)現(xiàn)當(dāng)前輸入結(jié)果與之前的計算掛鉤的目的。對RNN想要更深入的了解可以戳這里。
RNN的局限:
由于RNN模型如果需要實(shí)現(xiàn)長期記憶的話需要將當(dāng)前的隱含態(tài)的計算與前n次的計算掛鉤,即St = f(U*Xt + W1*St-1 + W2*St-2 + ... + Wn*St-n),那樣的話計算量會呈指數(shù)式增長,導(dǎo)致模型訓(xùn)練的時間大幅增加,因此RNN模型一般直接用來進(jìn)行長期記憶計算。
LSTM模型
LSTM(Long Short-Term Memory)模型是一種RNN的變型,最早由Juergen Schmidhuber提出的。經(jīng)典的LSTM模型結(jié)構(gòu)如下:
LSTM的特點(diǎn)就是在RNN結(jié)構(gòu)以外添加了各層的閥門節(jié)點(diǎn)。閥門有3類:遺忘閥門(forget gate),輸入閥門(input gate)和輸出閥門(output gate)。這些閥門可以打開或關(guān)閉,用于將判斷模型網(wǎng)絡(luò)的記憶態(tài)(之前網(wǎng)絡(luò)的狀態(tài))在該層輸出的結(jié)果是否達(dá)到閾值從而加入到當(dāng)前該層的計算中。如圖中所示,閥門節(jié)點(diǎn)利用sigmoid函數(shù)將網(wǎng)絡(luò)的記憶態(tài)作為輸入計算;如果輸出結(jié)果達(dá)到閾值則將該閥門輸出與當(dāng)前層的的計算結(jié)果相乘作為下一層的輸入(PS:這里的相乘是在指矩陣中的逐元素相乘);如果沒有達(dá)到閾值則將該輸出結(jié)果遺忘掉。每一層包括閥門節(jié)點(diǎn)的權(quán)重都會在每一次模型反向傳播訓(xùn)練過程中更新。更具體的LSTM的判斷計算過程如下圖所示:
LSTM模型的記憶功能就是由這些閥門節(jié)點(diǎn)實(shí)現(xiàn)的。當(dāng)閥門打開的時候,前面模型的訓(xùn)練結(jié)果就會關(guān)聯(lián)到當(dāng)前的模型計算,而當(dāng)閥門關(guān)閉的時候之前的計算結(jié)果就不再影響當(dāng)前的計算。因此,通過調(diào)節(jié)閥門的開關(guān)我們就可以實(shí)現(xiàn)早期序列對最終結(jié)果的影響。而當(dāng)你不不希望之前結(jié)果對之后產(chǎn)生影響,比如自然語言處理中的開始分析新段落或新章節(jié),那么把閥門關(guān)掉即可。(對LSTM想要更具體的了解可以戳這里)
下圖具體演示了閥門是如何工作的:通過閥門控制使序列第1的輸入的變量影響到了序列第4,6的的變量計算結(jié)果。
黑色實(shí)心圓代表對該節(jié)點(diǎn)的計算結(jié)果輸出到下一層或下一次計算;空心圓則表示該節(jié)點(diǎn)的計算結(jié)果沒有輸入到網(wǎng)絡(luò)或者沒有從上一次收到信號。
Python中實(shí)現(xiàn)LSTM模型搭建
Python中有不少包可以直接調(diào)用來構(gòu)建LSTM模型,比如pybrain, kears, tensorflow, cikit-neuralnetwork等(更多戳這里)。這里我們選用keras。(PS:如果操作系統(tǒng)用的linux或者mac,強(qiáng)推Tensorflow?。。。?/p>
因為LSTM神經(jīng)網(wǎng)絡(luò)模型的訓(xùn)練可以通過調(diào)整很多參數(shù)來優(yōu)化,例如activation函數(shù),LSTM層數(shù),輸入輸出的變量維度等,調(diào)節(jié)過程相當(dāng)復(fù)雜。這里只舉一個最簡單的應(yīng)用例子來描述LSTM的搭建過程。
應(yīng)用實(shí)例
基于某家店的某顧客的歷史消費(fèi)的時間推測該顧客前下次來店的時間。具體數(shù)據(jù)如下所示:
消費(fèi)時間 2015-05-15 14:03:51 2015-05-15 15:32:46 2015-06-28 18:00:17 2015-07-16 21:27:18 2015-07-16 22:04:51 2015-09-08 14:59:56 .. ..
具體操作:
1. 原始數(shù)據(jù)轉(zhuǎn)化
首先需要將時間點(diǎn)數(shù)據(jù)進(jìn)行數(shù)值化。將具體時間轉(zhuǎn)化為時間段用于表示該用戶相鄰兩次消費(fèi)的時間間隔,然后再導(dǎo)入模型進(jìn)行訓(xùn)練是比較常用的手段。轉(zhuǎn)化后的數(shù)據(jù)如下:
消費(fèi)間隔 0 44 18 0 54 .. ..
2.生成模型訓(xùn)練數(shù)據(jù)集(確定訓(xùn)練集的窗口長度)
這里的窗口指需要幾次消費(fèi)間隔用來預(yù)測下一次的消費(fèi)間隔。這里我們先采用窗口長度為3, 即用t-2, t-1,t次的消費(fèi)間隔進(jìn)行模型訓(xùn)練,然后用t+1次間隔對結(jié)果進(jìn)行驗證。數(shù)據(jù)集格式如下:X為訓(xùn)練數(shù)據(jù),Y為驗證數(shù)據(jù)。
PS: 這里說確定也不太合適,因為窗口長度需要根據(jù)模型驗證結(jié)果進(jìn)行調(diào)整的。
X1 X2 X3 Y 0 44 18 0 44 18 0 54 .. ..
注:直接這樣預(yù)測一般精度會比較差,可以把預(yù)測值Y根據(jù)數(shù)值bin到幾類,然后用轉(zhuǎn)換成one-hot標(biāo)簽再來訓(xùn)練會比較好。比如如果把Y按數(shù)值范圍分到五類(1:0-20,2:20-40,3:40-60,4:60-80,5:80-100)上式可化為:
X1 X2 X3 Y 0 44 18 0 44 18 0 4 ...
Y轉(zhuǎn)化成one-hot以后則是(關(guān)于one-hot編碼可以參考這里)
1 0 0 0 0 0 0 0 0 1 ...
3. 網(wǎng)絡(luò)模型結(jié)構(gòu)的確定和調(diào)整
這里我們使用python的keras庫。(用java的同學(xué)可以參考下deeplearning4j這個庫)。網(wǎng)絡(luò)的訓(xùn)練過程設(shè)計到許多參數(shù)的調(diào)整:比如
需要確定LSTM模塊的激活函數(shù)(activation fucntion)(keras中默認(rèn)的是tanh);
確定接收LSTM輸出的完全連接人工神經(jīng)網(wǎng)絡(luò)(fully-connected artificial neural network)的激活函數(shù)(keras中默認(rèn)為linear);
確定每一層網(wǎng)絡(luò)節(jié)點(diǎn)的舍棄率(為了防止過度擬合(overfit)),這里我們默認(rèn)值設(shè)定為0.2;
確定誤差的計算方式,這里我們使用均方誤差(mean squared error);
確定權(quán)重參數(shù)的迭代更新方式,這里我們采用RMSprop算法,通常用于RNN網(wǎng)絡(luò)。確定模型訓(xùn)練的epoch和batch size(關(guān)于模型的這兩個參數(shù)具體解釋戳這里)
一般來說LSTM模塊的層數(shù)越多(一般不超過3層,再多訓(xùn)練的時候就比較難收斂),對高級別的時間表示的學(xué)習(xí)能力越強(qiáng);同時,最后會加一層普通的神經(jīng)網(wǎng)路層用于輸出結(jié)果的降維。典型結(jié)構(gòu)如下:
如果需要將多個序列進(jìn)行同一個模型的訓(xùn)練,可以將序列分別輸入到獨(dú)立的LSTM模塊然后輸出結(jié)果合并后輸入到普通層。結(jié)構(gòu)如下:
4. 模型訓(xùn)練和結(jié)果預(yù)測
將上述數(shù)據(jù)集按4:1的比例隨機(jī)拆分為訓(xùn)練集和驗證集,這是為了防止過度擬合。訓(xùn)練模型。然后將數(shù)據(jù)的X列作為參數(shù)導(dǎo)入模型便可得到預(yù)測值,與實(shí)際的Y值相比便可得到該模型的優(yōu)劣。
實(shí)現(xiàn)代碼
時間間隔序列格式化成所需的訓(xùn)練集格式
import pandas as pd import numpy as np def create_interval_dataset(dataset, look_back): """ :param dataset: input array of time intervals :param look_back: each training set feature length :return: convert an array of values into a dataset matrix. """ dataX, dataY = [], [] for i in range(len(dataset) - look_back): dataX.append(dataset[i:i+look_back]) dataY.append(dataset[i+look_back]) return np.asarray(dataX), np.asarray(dataY) df = pd.read_csv("path-to-your-time-interval-file") dataset_init = np.asarray(df) # if only 1 column dataX, dataY = create_interval_dataset(dataset, lookback=3) # look back if the training set sequence length
這里的輸入數(shù)據(jù)來源是csv文件,如果輸入數(shù)據(jù)是來自數(shù)據(jù)庫的話可以參考這里
LSTM網(wǎng)絡(luò)結(jié)構(gòu)搭建
import pandas as pd import numpy as np import random from keras.models import Sequential, model_from_json from keras.layers import Dense, LSTM, Dropout class NeuralNetwork(): def __init__(self, **kwargs): """ :param **kwargs: output_dim=4: output dimension of LSTM layer; activation_lstm='tanh': activation function for LSTM layers; activation_dense='relu': activation function for Dense layer; activation_last='sigmoid': activation function for last layer; drop_out=0.2: fraction of input units to drop; np_epoch=10, the number of epoches to train the model. epoch is one forward pass and one backward pass of all the training examples; batch_size=32: number of samples per gradient update. The higher the batch size, the more memory space you'll need; loss='mean_square_error': loss function; optimizer='rmsprop' """ self.output_dim = kwargs.get('output_dim', 8) self.activation_lstm = kwargs.get('activation_lstm', 'relu') self.activation_dense = kwargs.get('activation_dense', 'relu') self.activation_last = kwargs.get('activation_last', 'softmax') # softmax for multiple output self.dense_layer = kwargs.get('dense_layer', 2) # at least 2 layers self.lstm_layer = kwargs.get('lstm_layer', 2) self.drop_out = kwargs.get('drop_out', 0.2) self.nb_epoch = kwargs.get('nb_epoch', 10) self.batch_size = kwargs.get('batch_size', 100) self.loss = kwargs.get('loss', 'categorical_crossentropy') self.optimizer = kwargs.get('optimizer', 'rmsprop') def NN_model(self, trainX, trainY, testX, testY): """ :param trainX: training data set :param trainY: expect value of training data :param testX: test data set :param testY: epect value of test data :return: model after training """ print "Training model is LSTM network!" input_dim = trainX[1].shape[1] output_dim = trainY.shape[1] # one-hot label # print predefined parameters of current model: model = Sequential() # applying a LSTM layer with x dim output and y dim input. Use dropout parameter to avoid overfitting model.add(LSTM(output_dim=self.output_dim, input_dim=input_dim, activation=self.activation_lstm, dropout_U=self.drop_out, return_sequences=True)) for i in range(self.lstm_layer-2): model.add(LSTM(output_dim=self.output_dim, input_dim=self.output_dim, activation=self.activation_lstm, dropout_U=self.drop_out, return_sequences=True)) # argument return_sequences should be false in last lstm layer to avoid input dimension incompatibility with dense layer model.add(LSTM(output_dim=self.output_dim, input_dim=self.output_dim, activation=self.activation_lstm, dropout_U=self.drop_out)) for i in range(self.dense_layer-1): model.add(Dense(output_dim=self.output_dim, activation=self.activation_last)) model.add(Dense(output_dim=output_dim, input_dim=self.output_dim, activation=self.activation_last)) # configure the learning process model.compile(loss=self.loss, optimizer=self.optimizer, metrics=['accuracy']) # train the model with fixed number of epoches model.fit(x=trainX, y=trainY, nb_epoch=self.nb_epoch, batch_size=self.batch_size, validation_data=(testX, testY)) # store model to json file model_json = model.to_json() with open(model_path, "w") as json_file: json_file.write(model_json) # store model weights to hdf5 file if model_weight_path: if os.path.exists(model_weight_path): os.remove(model_weight_path) model.save_weights(model_weight_path) # eg: model_weight.h6 return model
這里寫的只涉及LSTM網(wǎng)絡(luò)的結(jié)構(gòu)搭建,至于如何把數(shù)據(jù)處理規(guī)范化成網(wǎng)絡(luò)所需的結(jié)構(gòu)以及把模型預(yù)測結(jié)果與實(shí)際值比較統(tǒng)計的可視化,就需要根據(jù)實(shí)際情況做調(diào)整了。
以上是“Python中如何使用LSTM模型進(jìn)行時間序列預(yù)測分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計公司行業(yè)資訊頻道!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。