本節(jié)簡(jiǎn)介本節(jié)關(guān)于TFTS模塊的使用參考知乎-何之源-如何優(yōu)雅地用TensorFlow預(yù)測(cè)時(shí)間序列:TFTS庫(kù)詳細(xì)教程,。 如何在TensorFlow上使用LSTM來(lái)做時(shí)間序列預(yù)測(cè)是一個(gè)很老的話題,,然而一直沒有比較好的解決方案。在剛剛發(fā)布的TensorFlow1.3版本中,,在tf.contrib包下引入了一個(gè)Time Series模塊(TensorFlow Time Series,TFTS),。其源碼地址在github timeseries。TFTS提供了一套基礎(chǔ)的時(shí)間序列模型API,。目前提供AR,、Anomaly Mixture AR、LSTM三種預(yù)測(cè)模型,。 這里因?yàn)槭莿倓偘l(fā)布的庫(kù),,文檔匱乏,我們著重于介紹TFTS的以下幾個(gè)功能:
先看效果圖,,
這里涉及到的代碼保存在github-hzy46.網(wǎng)速不好的同學(xué)可以到或者在CSDN上下載。 TensorFlow更新注意 后面使用的LSTM模型的例子須使用TensorFlow最新的開發(fā)版的源碼,。具體來(lái)說(shuō),,要保證下面這句話可以成功執(zhí)行。 from tensorflow.contrib.timeseries.python.timeseries.estimators import TimeSeriesRegressor
如果執(zhí)行不成功,,則需要下面的更新操作,。 下載最新源碼(編譯源碼更新) 1. 首先卸載當(dāng)前的tensorflow pip uninstall tensorflow #gpu版 就是tensorflow-gpu
2. 參考官方的從源碼安裝tensorflow 參考TensorFlow官方安裝教程,。我的開發(fā)環(huán)境是Ubuntu16.04+1080顯卡,需要安裝gpu版本,。
''' 編譯 ''' bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package ''' 挺長(zhǎng)的一段編譯時(shí)間 生產(chǎn)pip包 ''' bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg ''' 安裝 ''' sudo pip install /tmp/tensorflow_pkg/tensorflow-1.3.0-py2-none-any.whl
如果出啥問題,,建議直接看官方教程來(lái)整,,有啥小問題,上stackoverflow上找找原因,。(從源碼編譯tensorflow前前后后花費(fèi)了我2天的時(shí)間,,現(xiàn)在整出來(lái)了,踩了不少的坑,,感覺下次會(huì)快很多了~) 現(xiàn)在9月初tensorflow的pip安裝版本還不支持這個(gè)TimeSeriesRegressor類,,等到后面版本穩(wěn)定更新了,應(yīng)該可以用下面pip工具更新,。 直接使用pip工具更新 因?yàn)楸敬斡玫降膸?kù)需要運(yùn)行在TensorFlow1.3版本,,而我的環(huán)境是Ubuntu下的1.0.1版本的TensorFlow。如果你不知道自己的TensorFlow是啥版本,,有一個(gè)簡(jiǎn)單的方法: 激活python編程環(huán)境,,鍵入以下代碼運(yùn)行即可。 import tensorflow as tf print(tf.__version__) # 查看tensorflow版本 print(tf.__path__) # 查看tensorflow安裝位置 ''' 輸出: 1.0.1 ['/root/anaconda2/lib/python2.7/site-packages/tensorflow'] '''
更新方法也很簡(jiǎn)單,,如果你的TensorFlow是普通的安裝,,直接在命令行鍵入以下命令: $: sudo pip install --upgrade tensorflow-gpu # 我安裝的是gpu版
等待更新完成即可。 import tensorflow as tf print(tf.__version__) # 查看tensorflow版本 print(tf.__path__) # 查看tensorflow安裝位置 ''' 輸出: 1.3.0 ['/root/anaconda2/lib/python2.7/site-packages/tensorflow'] '''
更新后可能會(huì)遇到的異常
到這里,,算是大功告成了~ 自定義LSTM循環(huán)神經(jīng)網(wǎng)絡(luò)進(jìn)行時(shí)間序列預(yù)測(cè)在使用TFTS庫(kù)前,,我們先利用自定義循環(huán)神經(jīng)網(wǎng)絡(luò)預(yù)測(cè)正弦函數(shù)。初步學(xué)習(xí)一下如何使用LSTM循環(huán)神經(jīng)網(wǎng)絡(luò)進(jìn)行時(shí)間序列預(yù)測(cè),,這里我們會(huì)使用TensorFlow的一個(gè)高級(jí)封裝工具-TFLearn(集成在tf.contrib.learn). 工程實(shí)現(xiàn) 1. 需要用到的模塊 # coding:utf8 import numpy as np import tensorflow as tf from tensorflow.contrib.learn.python.learn.estimators.estimator import SKCompat import matplotlib.pyplot as plt learn = tf.contrib.learn
2. 生成訓(xùn)練數(shù)據(jù)與測(cè)試數(shù)據(jù) 因?yàn)槭且A(yù)測(cè)正弦函數(shù),,這里我們使用np模塊下的np.sin函數(shù)生成訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)。 TRAINING_EXAMPLES = 10000 # 訓(xùn)練數(shù)據(jù)大小 TESTING_EXAMPLES = 1000 # 測(cè)試數(shù)據(jù)大小 SAMPLE_GAP = 0.01 #采樣間隔 TIMESTEPS = 10 # 循環(huán)神經(jīng)網(wǎng)絡(luò)截?cái)嚅L(zhǎng)度 def generate_data(seq): ''' 定義生成正弦函數(shù)數(shù)據(jù)函數(shù) :param seq: :return: X為訓(xùn)練數(shù)據(jù)序列,y為預(yù)測(cè)數(shù)據(jù) ''' X = [] y = [] for i in range(len(seq) - TIMESTEPS - 1): X.append([seq[i: i + TIMESTEPS]]) # 截取以i下標(biāo)開始的以TIMESTEPS為batch的數(shù)據(jù) y.append([seq[i + TIMESTEPS]]) # 預(yù)測(cè)i+TIMESTEPS的數(shù)據(jù) return np.array(X, dtype=np.float32), np.array(y, dtype=np.float32) # 生成數(shù)據(jù) # TRAINING_EXAMPLES訓(xùn)練數(shù)據(jù)個(gè)數(shù) SAMPLE_GAP采樣間隔 test_start = TRAINING_EXAMPLES * SAMPLE_GAP # 訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)個(gè)數(shù) test_end = (TRAINING_EXAMPLES + TESTING_EXAMPLES) * SAMPLE_GAP # np.linspace生成等差數(shù)列 即采樣橫軸數(shù)據(jù) # 從0到test_start,生成TRAINING_EXAMPLES個(gè)數(shù)據(jù)(即采樣間隔為SAMPLE_GAP) train_X, train_y = generate_data(np.sin(np.linspace( 0, test_start, TRAINING_EXAMPLES, dtype=np.float32))) # np.linspace生成等差數(shù)列 # test_X, test_y = generate_data(np.sin(np.linspace( test_start, test_end, TESTING_EXAMPLES, dtype=np.float32)))
注解: 訓(xùn)練數(shù)據(jù)TRAINING_EXAMPLES加上測(cè)試數(shù)據(jù)TESTING_EXAMPLES一共需要11000組,。 這里我們?cè)O(shè)置是采樣間隔SAMPLE_GAP是0.01,。故我們整個(gè)采樣距離是11000*0.01=110.也就是在sin函數(shù)上,x軸為[0,110]這段距離上均分為11000份,。 訓(xùn)練數(shù)據(jù)是以網(wǎng)絡(luò)的截?cái)嚅L(zhǎng)度為分割間距,。這里循環(huán)神經(jīng)網(wǎng)絡(luò)的截?cái)嚅L(zhǎng)度TIMESTEPS為10,。故我們的數(shù)據(jù)也是10個(gè)采樣點(diǎn)和對(duì)應(yīng)的sin值為一組,預(yù)測(cè)第11個(gè)點(diǎn),。(訓(xùn)練時(shí)候就是回歸第11個(gè)點(diǎn)的值).
下面是np.linspace和np.sin的用法示例: 3. 定義網(wǎng)絡(luò)模型 我們使用BasicLSTMCell和MultiRNNCell構(gòu)成一個(gè)hidden_size為30的2層的LSTM循環(huán)神經(jīng)網(wǎng)絡(luò)。需要注意的是不同版本下在創(chuàng)建LSTMCells的方法是不一樣的,。 HIDDEN_SIZE = 30 # 隱藏單元個(gè)數(shù) NUM_LAYERS = 2 #LSTM層數(shù) TRAINING_STEPS = 3000 # 訓(xùn)練數(shù)據(jù)輪數(shù) BATCH_SIZE = 32 # batch大小 def lstm_model(X, y): ''' 定義LSTM模型 :param X: 訓(xùn)練數(shù)據(jù) :param y: 預(yù)測(cè)標(biāo)簽 :return: ''' # 1.2版本后,tensorflow對(duì)使用BasicLSTMCell等 RNNCells生成cells有不同的處理方法,,這里多層的RNN建議采用這種創(chuàng)建cell方法 stacked_rnn = [] for iiLyr in range(NUM_LAYERS): stacked_rnn.append(tf.nn.rnn_cell.BasicLSTMCell(HIDDEN_SIZE, state_is_tuple=True)) cell = tf.nn.rnn_cell.MultiRNNCell(cells=stacked_rnn, state_is_tuple=True) #lstm_cell = tf.contrib.rnn.BasicLSTMCell(HIDDEN_SIZE, state_is_tuple=True) #1.2版本前 #cell = tf.contrib.rnn.MultiRNNCell([lstm_cell] * NUM_LAYERS) # 將多層LSTM結(jié)構(gòu)連接成RNN網(wǎng)絡(luò)并計(jì)算其前向傳播結(jié)果 output, _ = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32) # 只關(guān)注網(wǎng)絡(luò)的最后一個(gè)輸出結(jié)果,即為下一時(shí)刻的預(yù)測(cè)輸出 output = tf.reshape(output, [-1, HIDDEN_SIZE]) # 通過無(wú)激活函數(shù)的全聯(lián)接層計(jì)算線性回歸,,并將數(shù)據(jù)壓縮成一維數(shù)組的結(jié)構(gòu),。 predictions = tf.contrib.layers.fully_connected(output, 1, None) labels = tf.reshape(y, [-1]) predictions = tf.reshape(predictions, [-1]) # 定義平方差損失 loss = tf.losses.mean_squared_error(predictions, labels) # 創(chuàng)建模型優(yōu)化器并得到優(yōu)化步驟 train_op = tf.contrib.layers.optimize_loss( loss, tf.contrib.framework.get_global_step(), optimizer='Adagrad', learning_rate=0.1) return predictions, loss, train_op
4. 創(chuàng)建模型并訓(xùn)練 這里我們使用了tf.contrib.learn下的一個(gè)封裝模型工具Estimator。使用Estimator封裝好一個(gè)預(yù)測(cè)模型后((已訓(xùn)練),,我們對(duì)測(cè)試數(shù)據(jù)進(jìn)行了預(yù)測(cè),,再計(jì)算了下均方誤差,大體上的評(píng)估了一下模型的預(yù)測(cè)性能,。 # 封裝之前定義的lstm # 如果你的tensorflow1.2版本前已經(jīng)訓(xùn)練好了這樣的的一個(gè)模型,,在tensorflow更新后,重新生成模型,。 # 因?yàn)樵谛掳姹镜腡ensorflow里,,LSTM單元的文件改變了,這里我們簡(jiǎn)單的把以前的model_dir修改了,,保證創(chuàng)建了新的模型 regressor = SKCompat(learn.Estimator(model_fn=lstm_model, model_dir='Models/model_3')) # 擬合數(shù)據(jù) regressor.fit(train_X, train_y, batch_size=BATCH_SIZE, steps=TRAINING_STEPS) # 計(jì)算預(yù)測(cè)值 predicted = [[pred] for pred in regressor.predict(test_X)] # 計(jì)算MSE rmse = np.sqrt(((predicted - test_y) ** 2).mean(axis=0)) print ('Mean Square Error is: %f' % rmse[0])
Estimator工具 這里我們簡(jiǎn)單的介紹以下Estimator工具,。 參考TensorFlow 0.12 Estimators Models Layers學(xué)習(xí)筆記。Estimators的作用是:
總的來(lái)說(shuō),我們可以認(rèn)為tf.estimator工具是用來(lái)提供一個(gè)自定義模型的框架,,我們照著定義好的格式配置好輸入即可,。
5. 繪圖 使用plt將預(yù)測(cè)數(shù)據(jù)和測(cè)試數(shù)據(jù)繪制出來(lái),有一個(gè)直觀上的認(rèn)識(shí),。 fig = plt.figure() plot_predicted, = plt.plot(predicted, label='predicted') plot_test, = plt.plot(test_y[0:399], label='real_sin') plt.legend([plot_predicted, plot_test],['predicted', 'real_sin']) plt.show() fig.savefig('pre_sin.png')
利用TFTS進(jìn)行時(shí)間序列預(yù)測(cè)到這里算是切入主題了,,下面介紹如何使用TFTS模塊進(jìn)行時(shí)間序列預(yù)測(cè)。 載入數(shù)據(jù)部分 對(duì)于時(shí)間序列預(yù)測(cè)問題,,我們可以把數(shù)據(jù)抽象成:{觀察點(diǎn):觀察值},。例如某年一月的價(jià)格為120元,二月的價(jià)格為130元,,三月的價(jià)格為135元,,四月的價(jià)格為132元。那么觀察的時(shí)間點(diǎn)可以看做是1,2,3,4,,而在各時(shí)間點(diǎn)上觀察到的數(shù)據(jù)的值為120,130,135,132,。 TFTS庫(kù)提供了兩個(gè)數(shù)據(jù)讀取器NumpyReader和CSVReader. NumpyReader用于從Numpy數(shù)組中讀入數(shù)據(jù),下面舉一個(gè)demo: import numpy as np import matplotlib.pyplot as plt x = np.array(range(1000)) noise = np.random.uniform(-0.2, 0.2, 1000) # 隨機(jī)生成-0.2~0.2之間的數(shù)據(jù) y = np.sin(np.pi * x * 0.01) + x * 0.005 + noise # y=sin(0.01*pi*x) + 0.005*x + noise p = plt.plot(x, y) plt.show()
橫軸即’采樣點(diǎn)x’,縱軸為’采樣值y’. TFTS提供的讀入x和y的接口非常簡(jiǎn)單,,使用demo如下: data = { tf.contrib.timeseries.TrainEvalFeatures.TIMES: x, tf.contrib.timeseries.TrainEvalFeatures.VALUES: y, } reader = NumpyReader(data)
我們首先把x和y轉(zhuǎn)為Python中的dict.我們來(lái)分析以下上面data的寫法,。tf.contrib.timeseries.TrainEvalFeatures.TIMES就是一個(gè)字符串’times’,而對(duì)應(yīng)tf.contrib.timeseries.TrainEvalFeatures.VALUES也是一個(gè)字符串’values’.上面的data定義也可以寫成: data = { 'times' : x, 'values': y, }
至于為什么寫成上面的那個(gè)形式,,也是為了配合規(guī)范化,。 NumpyReader返回的對(duì)象有一個(gè)read_full()方法,該方法用于從Reader中讀取所有的數(shù)據(jù),,但需要注意的是:read_full()會(huì)產(chǎn)生讀取隊(duì)列(這樣的處理訓(xùn)練數(shù)據(jù)的方法和TensorFlow開源的AlexNet網(wǎng)絡(luò)上對(duì)輸入數(shù)據(jù)做增強(qiáng)操作使用的方法類似),,這要求我們?cè)谑褂迷摲椒ㄇ埃枰?strong>先調(diào)用tf.train.start_queue_runners啟動(dòng)隊(duì)列,,然后才能讀取數(shù)據(jù),。使用的demo如下: with tf.Session() as sess: full_data = reader.read_full() coord = tf.train.Coordinator() # 創(chuàng)建一個(gè)線程協(xié)調(diào)器 threads = tf.train.start_queue_runners(sess=sess, coord=coord) # 啟動(dòng)線程隊(duì)列 print('times shape:', full_data['times']) print('values shape:', full_data['values']) print(sess.run(full_data)['times'][0:10]) print(sess.run(full_data)['values'][0:10]) coord.request_stop() ''' 輸出: times shape: Tensor('Squeeze_1:0', shape=(1000,), dtype=int64) values shape: Tensor('Squeeze:0', shape=(1000, 1), dtype=float64) [0 1 2 3 4 5 6 7 8 9] [[-0.09581681] [ 0.01284531] [ 0.1107236 ] [ 0.08856841] [ 0.19104294] [ 0.32795446] [ 0.17780316] [ 0.35017529] [ 0.10477021] [ 0.16101822]] '''
通常在訓(xùn)練模型時(shí),我們采需要的是minibatch形式的訓(xùn)練數(shù)據(jù),,TFTS庫(kù)提供了tf.contrib.timeseries.RandomWindowInputFn方法用于在reader中隨機(jī)選取window_size大小的數(shù)據(jù)組成一組序列數(shù)據(jù),。demo如下: train_input_fn = tf.contrib.timeseries.RandomWindowInputFn( reader, batch_size=2, window_size=10) with tf.Session() as sess: batch_data = train_input_fn.create_batch() coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess, coord=coord) one_batch = sess.run(batch_data[0]) coord.request_stop() print('one_batch_data:', one_batch) ''' 即一個(gè)batch為2組序列數(shù)據(jù),每組序列數(shù)據(jù)有10條數(shù)據(jù),。 輸出: one_batch_data: { 'values': array([[[ 1.21827106], [ 1.37975747], [ 1.15419451], [ 1.07579377], [ 1.19008057], [ 1.32173953], [ 1.2152622 ], [ 1.31092923], [ 1.26184174], [ 1.25915473]], [[ 0.08465949], [-0.0859257 ], [-0.02987006], [ 0.17472125], [ 0.23542243], [ 0.2032668 ], [ 0.07650485], [ 0.20822309], [ 0.30753332], [ 0.16054565]]]), 'times': array([[61, 62, 63, 64, 65, 66, 67, 68, 69, 70], [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]])} '''
TFTS從Numpy中讀取數(shù)據(jù)的流程大概操作就是這樣了~ 從CSV文件中讀入時(shí)間序列數(shù)據(jù) TFTS還提供了CSVReader用于讀取CSV文件,。 項(xiàng)目中提供了一個(gè)input_input_csv.py文件用于處理csv文件,,這里處理的文件是’./data/period_trend.csv’. 這里CSV的文件形式如下(截取): 1,-0.6656603714 2,-0.1164380359 3,0.7398626488 4,0.7368633029 5,0.2289480898 6,2.257073255 7,3.023457405 8,2.481161007 9,3.773638612 10,5.059257738 11,3.553186083 12,4.554486452 13,3.655475698 14,3.419647598 15,4.303376245 16,4.830153934 17,7.253057441 18,5.064802335 19,5.448082106 20,6.251301517 ...
CSV的第一列數(shù)據(jù)為時(shí)間點(diǎn),第二列數(shù)據(jù)為對(duì)應(yīng)的觀察值,。 CSVReader的操作步驟除了讀取文件的部分不同,,后面的操作和前面的NumpyReader是一樣的。操作的demo如下: from __future__ import print_function import tensorflow as tf csv_file_name = './data/period_trend.csv' reader = tf.contrib.timeseries.CSVReader(csv_file_name) with tf.Session() as sess: data = reader.read_full() coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess, coord=coord) print(sess.run(data)) coord.request_stop() train_input_fn = tf.contrib.timeseries.RandomWindowInputFn(reader, batch_size=4, window_size=16) with tf.Session() as sess: data = train_input_fn.create_batch() coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess, coord=coord) batch1 = sess.run(data[0]) batch2 = sess.run(data[0]) coord.request_stop() print('batch1:', batch1) print('batch2:', batch2) ''' 輸出: {'values': array([[ -0.66566038], [ -0.11643804], [ 0.73986262], [ 0.73686332], [ 0.22894809], [ 2.25707316], [ 3.02345729], ... dtype=float32), 'times': array([ 1, 2, 3, 4, 5, 6, ...,,500])} batch1: {'values': array([[[ 9.75562382], [ 9.1494894 ], [ 8.94796562], [ 9.1767683 ],dtype=float32), 'times': array([[ 98, 99,,...,129]])} batch2: {'values': array([[[ 4.97288084], [ 5.21278238],...,dtype=float32), 'times': array([[ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97],...,,226]])} '''
到這里為止,,載入數(shù)據(jù)部分到這里就算結(jié)束了。 使用AR模型預(yù)測(cè)時(shí)間序列 AR模型是一種線性預(yù)測(cè),,即已知N個(gè)數(shù)據(jù),,可由模型推出第N點(diǎn)前面或后面的數(shù)據(jù)(設(shè)推出P點(diǎn)),所以其本質(zhì)類似于插值,,其目的都是為了增加有效數(shù)據(jù),,只是AR模型是由N點(diǎn)遞推,而插值是由兩點(diǎn)(或少數(shù)幾點(diǎn))去推導(dǎo)多點(diǎn),,所以AR模型要比插值方法效果更好。 代碼實(shí)現(xiàn) 產(chǎn)生數(shù)據(jù) 產(chǎn)生數(shù)據(jù)的方法就是上面介紹的方法,。 x = np.array(range(1000)) noise = np.random.uniform(-0.2, 0.2, 1000) y = np.sin(np.pi * x / 100) + x / 200. + noise plt.plot(x, y) plt.savefig('timeseries_y.jpg') data = { tf.contrib.timeseries.TrainEvalFeatures.TIMES: x, tf.contrib.timeseries.TrainEvalFeatures.VALUES: y, } reader = NumpyReader(data) train_input_fn = tf.contrib.timeseries.RandomWindowInputFn( reader, batch_size=16, window_size=40)
創(chuàng)建ar模型 創(chuàng)建ar模型,,我們需要使用tf.contrib.timeseries.ARRegressor類 先看下ARRegressor類 class ARRegressor(_TimeSeriesRegressor): ''' ARRegressor是基于滑窗模型的。這要求輸入窗口大小要固定為'input_window_size',,輸出窗口大小固定為'output_window_size'. 同時(shí)這兩個(gè)參數(shù)的和必須等于window_size(滿足訓(xùn)練或評(píng)估時(shí)使用的input_fn),。建議使用'RandomWindowInputFn'(就是上面講的隨機(jī)產(chǎn)生batch數(shù)據(jù)的函數(shù))產(chǎn)生訓(xùn)練或者評(píng)估。 ''' def __init__(self, periodicities, input_window_size, output_window_size, num_features, num_time_buckets=10, loss=ar_model.ARModel.NORMAL_LIKELIHOOD_LOSS, hidden_layer_sizes=None, anomaly_prior_probability=None, anomaly_distribution=None, optimizer=None, model_dir=None, config=None): ''' 參數(shù): periodicities: value or a list of values. 輸入信號(hào)的周期,。 input_window_size: 回歸時(shí)給定的輸入數(shù)據(jù)時(shí)間步數(shù). output_window_size: 預(yù)測(cè)時(shí)間步數(shù),,建議設(shè)置>1. num_features: 時(shí)間序列的維度.(數(shù)據(jù)的觀察值) loss: SQUARED_LOSS 或者 NORMAL_LIKELIHOOD_LOSS. hidden_layer_sizes: 默認(rèn)即可. anomaly_distribution;anomaly_distribution: 默認(rèn)即可,,指定即構(gòu)成混合模型 optimizer: defaults to Adagrad with step size 0.1. model_dir:模型存儲(chǔ)地址.(上面Estimator有講) config: See `Estimator`. '''
總的來(lái)說(shuō),,需要填的參數(shù)有periodicities,input_window_size,output_window_size,num_features,loss。其它的參數(shù)默認(rèn)即可,。 這里需要注意的有input_window_size + output_window_size = window_size.(RandomWindowInputFn生成數(shù)據(jù)里面的window_size).我們?cè)谏厦娴纳蓴?shù)據(jù)使用的window_size=40.下面使用的是input_window_size=30, output_window_size=10.就是輸入序列30個(gè),,預(yù)測(cè)10個(gè)。 num_features即時(shí)間序列的維度,。就是在一個(gè)時(shí)間點(diǎn)上觀察到的數(shù)據(jù)維度,。我們這里每一步都是一個(gè)單獨(dú)的值,所以num_features=1,。 periodicities是信號(hào)的周期分量的周期,,我們信號(hào)的表達(dá)式為: y=sin(0.01?π?x)+0.005?x+noise y=sin(0.01?π?x)+0.005?x+noise y的周期分量的frequency為2?π?(1/f) 2?π?(1/f),故f=200,所以periodicities=200 f=200,所以periodicities=200,。 loss的取值現(xiàn)在支持NORMAL_LIKELIHOOD_LOSS和SQUARED_LOSS。 ar = tf.contrib.timeseries.ARRegressor( periodicities=200, input_window_size=30, output_window_size=10, num_features=1, loss=tf.contrib.timeseries.ARModel.NORMAL_LIKELIHOOD_LOSS) ''' (input_window_size=30) + (output_window_size=10) = (window_size=40) '''
訓(xùn)練評(píng)估模型并預(yù)測(cè) 使用train函數(shù)傳入創(chuàng)建好的數(shù)據(jù)train_input_fn訓(xùn)練模型即可. ar.train(input_fn=train_input_fn, steps=6000)
接下來(lái)就是對(duì)模型進(jìn)行評(píng)估,,首先我們使用AR模型提供的evaluate函數(shù),,這里evaluation的處理是使用訓(xùn)練好的模型在原先的訓(xùn)練集上進(jìn)行計(jì)算,由此我們可以觀察到模型的擬合效果. evaluation_input_fn = tf.contrib.timeseries.WholeDatasetInputFn(reader) evaluation = ar.evaluate(input_fn=evaluation_input_fn, steps=1) # keys of evaluation: ['covariance', 'loss', 'mean', 'observed', 'start_tuple', 'times', 'global_step'] # evaluation['covariance']代表協(xié)方差 evaluation['loss']代表?yè)p失 etc..
如果要理解這里evaluate函數(shù)的邏輯,,這里AR模型:每次都接收長(zhǎng)度為30的輸入觀測(cè)序列,,并輸出長(zhǎng)度為10的預(yù)測(cè)序列。以此為規(guī)則,,每次移動(dòng)步長(zhǎng)為1,,以此類推,整個(gè)訓(xùn)練集長(zhǎng)度為1000的序列,,最終我們得到970個(gè)預(yù)測(cè)值,。 這970個(gè)預(yù)測(cè)值記錄在evaluation[‘mean’]中;evaluation還有其他幾個(gè)鍵值:evaluation[‘loss’]表示總的損失,evaluation[‘times’]表示evaluation[‘mean’]對(duì)應(yīng)的時(shí)間點(diǎn)等等. 評(píng)估完模型后,,下面該是使用模型了,,這里我們會(huì)用到predict函數(shù)來(lái)預(yù)測(cè),傳入?yún)?shù)為evaluation[‘start_tuple’]會(huì)被用于之后的預(yù)測(cè)中,,它相當(dāng)于最后30步的輸出值和對(duì)應(yīng)的時(shí)間點(diǎn),。以此為起點(diǎn)(也就是給定觀察數(shù)據(jù)),我們可以對(duì)1000步以后的值進(jìn)行預(yù)測(cè),,對(duì)應(yīng)的代碼為: (predictions,) = tuple(ar.predict( input_fn=tf.contrib.timeseries.predict_continuation_input_fn( evaluation, steps=250)))
這里的代碼在1000步之后又像后預(yù)測(cè)了250個(gè)時(shí)間點(diǎn),。對(duì)應(yīng)的值就保存在predictions[‘mean’]中。我們可以把觀測(cè)到的值,、模型擬合的值,、預(yù)測(cè)值用下面的代碼畫出來(lái): plt.figure(figsize=(15, 5)) plt.plot(data['times'].reshape(-1), data['values'].reshape(-1), label='origin') plt.plot(evaluation['times'].reshape(-1), evaluation['mean'].reshape(-1), label='evaluation') plt.plot(predictions['times'].reshape(-1), predictions['mean'].reshape(-1), label='prediction') plt.xlabel('time_step') plt.ylabel('values') plt.legend(loc=4) plt.savefig('predict_result.jpg')
使用LSTM預(yù)測(cè)單變量時(shí)間序列 注意:以下LSTM模型的例子必須使用TensorFlow最新的開發(fā)版的源碼。具體來(lái)說(shuō),,要保證 from tensorflow.contrib.timeseries.python.timeseries.estimators import TimeSeriesRegressor
可以成功執(zhí)行,。(就是前面說(shuō)的需要安裝最新版的tensorflow) 給出兩個(gè)用LSTM預(yù)測(cè)時(shí)間序列模型的例子,分別是train_lstm.py和train_lstm_multivariate.py,。前者是在LSTM中進(jìn)行單變量的時(shí)間序列預(yù)測(cè),,后者是使用LSTM進(jìn)行多變量時(shí)間序列預(yù)測(cè)。為了使用LSTM模型,,我們需要先使用TFTS庫(kù)對(duì)其進(jìn)行定義,,定義模型的代碼來(lái)源于TFTS的示例源碼,在train_lstm.py和train_lstm_multivariate.py中分別拷貝了一份,。 產(chǎn)生訓(xùn)練數(shù)據(jù) 這里我們產(chǎn)生的數(shù)據(jù)公式修改一下 y=sin(π?0.02?x)+cos(π?0.02?x)+sin(π?0.04?x)+noise y=sin(π?0.02?x)+cos(π?0.02?x)+sin(π?0.04?x)+noise 同樣用函數(shù)加噪聲的方法生成一個(gè)模擬的時(shí)間序列數(shù)據(jù): x = np.array(range(1000)) noise = np.random.uniform(-0.2, 0.2, 1000) y = np.sin(np.pi * x / 50 ) + np.cos(np.pi * x / 50) + np.sin(np.pi * x / 25) + noise data = { tf.contrib.timeseries.TrainEvalFeatures.TIMES: x, tf.contrib.timeseries.TrainEvalFeatures.VALUES: y, } ''' plt.plot(x, y) plt.savefig('train_data.jpg') ''' reader = NumpyReader(data) train_input_fn = tf.contrib.timeseries.RandomWindowInputFn( reader, batch_size=4, window_size=100) # batch_size為4 序列長(zhǎng)度為100
產(chǎn)生數(shù)據(jù)如下: 定義訓(xùn)練模型并預(yù)測(cè) 這里使用TFTS包內(nèi)提供的TimeSeriesRegressor模型,。其中_LSTMModel來(lái)自TFTS包的官方例子。
這里我們使用的模型參數(shù)為num_features = 1表示單變量時(shí)間序列,即每個(gè)時(shí)間點(diǎn)上觀察到的量只是一個(gè)單獨(dú)的數(shù)值,。num_units=128表示使用隱層為128大小的LSTM模型,。后續(xù)的訓(xùn)練,評(píng)估,,預(yù)測(cè)和前面講的代碼類似,。在以后的1000組數(shù)據(jù)上,我們向后預(yù)測(cè)了200組數(shù)據(jù),。 代碼如下: estimator = ts_estimators.TimeSeriesRegressor( model=_LSTMModel(num_features=1, num_units=128), optimizer=tf.train.AdamOptimizer(0.001)) estimator.train(input_fn=train_input_fn, steps=2000) evaluation_input_fn = tf.contrib.timeseries.WholeDatasetInputFn(reader) evaluation = estimator.evaluate(input_fn=evaluation_input_fn, steps=1) # Predict starting after the evaluation 預(yù)測(cè)后續(xù)的200組數(shù)據(jù) (predictions,) = tuple(estimator.predict( input_fn=tf.contrib.timeseries.predict_continuation_input_fn( evaluation, steps=200)))
繪制預(yù)測(cè)數(shù)據(jù)圖 observed_times = evaluation['times'][0] observed = evaluation['observed'][0, :, :] evaluated_times = evaluation['times'][0] evaluated = evaluation['mean'][0] predicted_times = predictions['times'] predicted = predictions['mean'] plt.figure(figsize=(15, 5)) plt.axvline(999, linestyle='dotted', linewidth=4, color='r') observed_lines = plt.plot(observed_times, observed, label='observation', color='k') evaluated_lines = plt.plot(evaluated_times, evaluated, label='evaluation', color='g') predicted_lines = plt.plot(predicted_times, predicted, label='prediction', color='r') plt.legend(handles=[observed_lines[0], evaluated_lines[0], predicted_lines[0]], loc='upper left') plt.savefig('predict_result.jpg')
使用LSTM預(yù)測(cè)多變量時(shí)間序列 與上面的使用LSTM預(yù)測(cè)單變量時(shí)間序列不同的地方在于數(shù)據(jù)的讀取和模型的預(yù)測(cè)量,。使用原理實(shí)質(zhì)上是一致的。 獲取訓(xùn)練數(shù)據(jù) 所謂多變量時(shí)間序列,,就是指在每個(gè)時(shí)間點(diǎn)上的觀測(cè)量有多個(gè)值,。在data/multivariate_periods.csv文件中,保存了一個(gè)多變量時(shí)間序列的數(shù)據(jù):(下面是截取) 0,0.926906299771,1.99107237682,2.56546245685,3.07914768197,4.04839057867 1,0.108010001864,1.41645361423,2.1686839775,2.94963962176,4.1263503303 2,-0.800567600028,1.0172132907,1.96434754116,2.99885333086,4.04300485864 3,0.0607042871898,0.719540073421,1.9765012584,2.89265588817,4.0951014426 4,0.933712200629,0.28052120776,1.41018552514,2.69232603996,4.06481164223 5,-0.171730652974,0.260054421028,1.48770816369,2.62199129293,4.44572807842 6,-1.00180162933,0.333045158863,1.50006392277,2.88888309683,4.24755865606 7,0.0580061875336,0.688929398826,1.56543458772,2.99840358953,4.52726873347 8,0.764139447412,1.24704875327,1.77649279698,3.13578593851,4.63238922951 9,-0.230331874785,1.47903998963,2.03547545751,3.20624030377,4.77980005228 10,-1.03846045211,2.01133000781,2.31977503972,3.67951536251,5.09716775897 11,0.188643592253,2.23285349038,2.68338482249,3.49817168611,5.24928239634 12,0.91207302309,2.24244446841,2.71362604985,3.96332587625,5.37802271594 13,-0.296588665881,2.02594634141,3.07733910479,3.99698324956,5.56365901394 14,-0.959961476551,1.45078629833,3.18996420137,4.3763059609,5.65356015609 15,0.46313530679,1.01141441548,3.4980215948,4.20224896882,5.88842247449 16,0.929354125798,0.626635305936,3.70508262244,4.51791573544,5.73945973251
即每個(gè)時(shí)間步上能觀察到多個(gè)數(shù)據(jù)變量(這里有5組數(shù)據(jù)),。舉個(gè)簡(jiǎn)單的例子:如果現(xiàn)在我在跑步,,每個(gè)時(shí)間步上,可以獲取到我的心跳,,血壓,,體溫。這就是在每個(gè)時(shí)間步上能觀察到3個(gè)數(shù)據(jù)變量,。 下面依舊是使用CSVReader處理數(shù)據(jù),,區(qū)別在column_names參數(shù),該參數(shù)告訴CSVReader那些變量是對(duì)應(yīng)的時(shí)間步和變量,。 csv_file_name = path.join('./data/multivariate_periods.csv') reader = tf.contrib.timeseries.CSVReader( csv_file_name, column_names=((tf.contrib.timeseries.TrainEvalFeatures.TIMES,) + (tf.contrib.timeseries.TrainEvalFeatures.VALUES,) * 5)) train_input_fn = tf.contrib.timeseries.RandomWindowInputFn( reader, batch_size=4, window_size=32)
定義訓(xùn)練模型并預(yù)測(cè) 這里與上面的程序不同的地方在于_LSTMModel中參數(shù)num_features=5.即能觀察的數(shù)據(jù)量維度為5.本次向后預(yù)測(cè)的數(shù)據(jù)為100組,。(訓(xùn)練數(shù)據(jù)100組) estimator = ts_estimators.TimeSeriesRegressor( model=_LSTMModel(num_features=5, num_units=128), optimizer=tf.train.AdamOptimizer(0.001)) estimator.train(input_fn=train_input_fn, steps=200) evaluation_input_fn = tf.contrib.timeseries.WholeDatasetInputFn(reader) evaluation = estimator.evaluate(input_fn=evaluation_input_fn, steps=1) # Predict starting after the evaluation (predictions,) = tuple(estimator.predict( input_fn=tf.contrib.timeseries.predict_continuation_input_fn( evaluation, steps=100)))
繪制預(yù)測(cè)圖 observed_times = evaluation['times'][0] observed = evaluation['observed'][0, :, :] evaluated_times = evaluation['times'][0] evaluated = evaluation['mean'][0] predicted_times = predictions['times'] predicted = predictions['mean'] plt.figure(figsize=(15, 5)) plt.axvline(99, linestyle='dotted', linewidth=4, color='r') observed_lines = plt.plot(observed_times, observed, label='observation', color='k') evaluated_lines = plt.plot(evaluated_times, evaluated, label='evaluation', color='g') predicted_lines = plt.plot(predicted_times, predicted, label='prediction', color='r') plt.legend(handles=[observed_lines[0], evaluated_lines[0], predicted_lines[0]], loc='upper left') plt.savefig('predict_result.jpg')
總結(jié)TFTS是Tensorflow官方提供的基于LSTM模型的時(shí)序預(yù)測(cè)工具,可以用于常見的時(shí)序模型上(替代HMM),。這里講了如果使用TFTS模型讀取數(shù)據(jù)并產(chǎn)生訓(xùn)練數(shù)據(jù),同時(shí)講了如果使用TFTS模塊自帶的AR和LSTM模型,。 |
|