爲了預測股票,我用TensorFlow深度學習了股市數據

完整源碼可在微信公衆號:「01二進制」後臺回覆:「股市分析」獲取html

閱讀此文前建議先閱讀《找對象的過程當中,我居然理解了什麼是機器學習!》python

前言

相信你們這幾天或多或少的都開始關注到股市了,雖然我還不是很懂裏面的一些套路,可是從最近各個公衆號的推送裏面,我也看到最近的股市確實是形勢大好。對不少人來講,股票就和房價同樣,他的升與降牽動着衆多人的心。這幾天不少qq羣、微信羣都開始討論起股票了,各位坊間大神也紛紛開始預測各類股票走勢了。vim

股票價格是典型的時間序列數據(簡稱時序數據),會受到經濟環境、政府政策、人爲操做多種複雜因素的影響,因此說股票價格預測是一件很是唬人的事情。可是基於歷史數據,以股票價格爲例,介紹如何對時序數據進行預測,仍然值得一作。bash

不過今天咱們不聊股市,由於我也不是很懂,今天咱們來聊聊咱們知道的東西。現在深度學習在金融市場的應用愈來愈普遍,咱們可否利用已有的歷史數據經過深度學習的方式來進行預測呢?微信

準備工做

答案天然是能夠的,雖然咱們沒法很是準確的進行預測,可是做爲一個深度學習入手的項目是完徹底全能夠的。網絡

實驗環境

老樣子,以避免出現因環境致使的問題,先將實驗環境列出:架構

  • MacOS 10.14.3
  • Python 3.6.8(Anaconda)
  • Jupyter Notebook
  • 使用的包有:
    • TensorFlow
    • Keras
    • matplotlib
    • pandas

數據

這次實驗,咱們採用STATWORXS&P 500股價數據,該數據集爬取自Google Finance API,已經進行過缺失值處理。他們的官方網站是:www.statworx.com/。框架

數據集可在微信公衆號:「01二進制」後臺回覆:「股市數據集」獲取dom

數據預覽

在這裏咱們仍是使用pandas,主要用於數據清洗和整理機器學習

import pandas as pd
data=pd.read_csv('data/data_stocks.csv')
data.info()
複製代碼

執行data.info()能夠查看特徵的概要:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 41266 entries, 0 to 41265
Columns: 502 entries, DATE to NYSE.ZTS
dtypes: float64(501), int64(1)
memory usage: 158.0 MB
複製代碼

從上述結果可知:該數據集數據共502列,41266行,502列分別爲:

  • DATE:該行數據的時間戳
  • SP500:能夠理解爲大盤指數
  • 其餘:能夠理解爲500支個股的股價

查看數據的前五行

data.head()
複製代碼

繪製大盤趨勢折線圖

plt.plot(data['SP500'])
複製代碼

結果以下:

Tips:這次實驗的調試環境爲Jupyter Notebook,咱們最好在開頭導入matplotlib包的時候在加一行%matplotlib inline,這樣就能夠在Jupyter Notebook中內嵌繪圖,而且省略掉plt.show()這一步。

數據整理

在這裏,咱們須要將數據集分爲訓練和測試數據。分配比爲8:2,即訓練數據包含總數據集的80%。固然在這以前咱們須要先將DATE這個無關變量捨去。

data.drop('DATE', axis=1, inplace=True)
data_train = data.iloc[:int(data.shape[0] * 0.8), :]
data_test = data.iloc[int(data.shape[0] * 0.8):, :]
複製代碼

咱們來查看一下訓練集和測試集的shape

數據歸一化

將屬性縮放到一個指定的最大和最小值(一般是(-1,1))之間,這能夠經過sklearn.preprocessing.MinMaxScaler類實現。

使用這種方法的目的包括:

  1. 對於方差很是小的屬性能夠加強其穩定性。

  2. 維持稀疏矩陣中爲0的條目。

scaler = MinMaxScaler(feature_range=(-1, 1))
scaler.fit(data_train)
data_train = scaler.transform(data_train)
data_test = scaler.transform(data_test)
複製代碼

預測

在這次預測過程當中,我採用TensorFlow這個深度學習框架,它是目前領先的深度學習和神經網絡計算框架。這一部分推薦有基礎的人閱讀,在這推薦我還在整理的TensorFlow系列,有興趣的能夠了解下。

這裏咱們須要解決的問題是:使用當前時刻的500支個股股價,預測當前時刻的大盤指數。即一個迴歸問題,輸入共500維特徵,輸出一維,即[None, 500] => [None, 1]

設置X與Y

X_train = data_train[:, 1:]
y_train = data_train[:, 0]
X_test = data_test[:, 1:]
y_test = data_test[:, 0]
複製代碼

這裏的x和y是已經分類好的數據集,只是用X和Y兩個變量表示,能夠理解爲函數裏面的X和Y。

設置超參數

input_dim = X_train.shape[1]
output_dim = 1
hidden_1 = 1024
hidden_2 = 512
hidden_3 = 256
hidden_4 = 128
batch_size = 256
epochs = 10
複製代碼

這裏咱們設置了幾個超參數,input_dim表示輸入數據的維度,即500。output_dim表示輸出數據的維度,即1。在該模型中設置了4層隱藏層,第一層包含1024個神經元,略大於輸入大小的兩倍。 後續的隱藏層老是前一層的一半大小,即分別爲512,256和128個神經元。 每一個後續層的神經元數量的減小壓縮了網絡在先前層中識別的信息。 固然,其餘網絡架構和神經元配置也是可能的,只是因爲本文只是一個入門的項目因此並未深究。

在機器學習中,超參數是在開始學習過程以前設置值的參數,而不是經過訓練獲得的參數數據。一般狀況下,須要對超參數進行優化,給學習機選擇一組最優超參數,以提升學習的性能和效果。

設置佔位符(placeholder)

X = tf.placeholder(shape=[None, input_dim], dtype=tf.float32)
Y = tf.placeholder(shape=[None], dtype=tf.float32)
複製代碼

爲了適應咱們的模型,咱們須要兩個佔位符:X(神經網絡的輸入)和Y(神經網絡的輸出)。

設置神經網絡

根據以前設置好的超參數進行神經網絡的配置,其中w爲權重,b爲偏置值

# 第一層
W1 = tf.get_variable('W1', [input_dim, hidden_1], initializer=tf.contrib.layers.xavier_initializer(seed=1))
b1 = tf.get_variable('b1', [hidden_1], initializer=tf.zeros_initializer())
# 第二層
W2 = tf.get_variable('W2', [hidden_1, hidden_2], initializer=tf.contrib.layers.xavier_initializer(seed=1))
b2 = tf.get_variable('b2', [hidden_2], initializer=tf.zeros_initializer())
# 第三層
W3 = tf.get_variable('W3', [hidden_2, hidden_3], initializer=tf.contrib.layers.xavier_initializer(seed=1))
b3 = tf.get_variable('b3', [hidden_3], initializer=tf.zeros_initializer())
# 第四層
W4 = tf.get_variable('W4', [hidden_3, hidden_4], initializer=tf.contrib.layers.xavier_initializer(seed=1))
b4 = tf.get_variable('b4', [hidden_4], initializer=tf.zeros_initializer())
# 輸出層
W5 = tf.get_variable('W5', [hidden_4, output_dim], initializer=tf.contrib.layers.xavier_initializer(seed=1))
b5 = tf.get_variable('b5', [output_dim], initializer=tf.zeros_initializer())
複製代碼

瞭解輸入層,隱藏層和輸出層之間所需的變量尺寸很是重要。做爲多層感知器(MLP,這裏使用的網絡類型)的一個經驗法則,前一層的第二維是當前層中權重矩陣的第一維。這可能聽起來很複雜,但實質上只是每一個圖層都將其輸出做爲輸入傳遞到下一圖層。誤差維度等於當前圖層的權重矩陣的第二維度,其對應於該層中的神經元的數量。

設置網絡體系結構

在定義所需的權重和偏置變量後,須要指定網絡拓撲結構和網絡結構。所以,佔位符(數據)和變量(權重和偏置)須要組合成一個連續矩陣乘法系統。

h1 = tf.nn.relu(tf.add(tf.matmul(X, W1), b1))
h2 = tf.nn.relu(tf.add(tf.matmul(h1, W2), b2))
h3 = tf.nn.relu(tf.add(tf.matmul(h2, W3), b3))
h4 = tf.nn.relu(tf.add(tf.matmul(h3, W4), b4))
out = tf.transpose(tf.add(tf.matmul(h4, W5), b5))
複製代碼

此外,網絡的隱藏層須要被激活函數激活。激活函數是網絡體系結構的重要組成部分,由於它們將非線性引入到系統中。這裏採用最多見的ReLU激活函數。

下圖說明了網絡架構。 該模型由三個主要構建塊組成。 輸入層,隱藏層和輸出層。 該體系結構稱爲前饋網絡。 前饋表示該批數據僅從左向右流動。 其餘網絡架構,例如遞歸神經網絡,也容許數據在網絡中「向後」流動。

設置損失函數(loss function)和優化器(Optimizer)

loss = tf.reduce_mean(tf.squared_difference(out, Y))
optimizer = tf.train.AdamOptimizer().minimize(loss)
複製代碼

這一部分沒啥好說的,記住這麼寫就能夠了,想了解的話能夠去個人TensorFlow中瞭解下。

執行訓練過程

在定義好神經網絡的佔位符,結構,損失函數函數和優化器以後,咱們就能夠開始對模型進行訓練了。訓練數據集分爲n / batch_size批次,這些批次按順序送入網絡。 此時佔位符X和Y開始起做用。 它們存儲輸入和目標數據,並將它們做爲輸入和目標呈現給網絡。

數據X分批次流經網絡,直到到達輸出層。 在那裏,TensorFlow將模型預測與當前批次中實際觀察到的目標Y進行比較。 以後,TensorFlow進行優化步驟並更新與所選學習方案相對應的網絡參數。 更新了權重和誤差後,對下一批進行採樣,並重復該過程。 該過程將繼續,直到全部批次都已呈現給網絡。對全部數據進行一次全面掃描被稱爲一個epoch(輪)

一旦達到了最大數量的epochs或用戶定義的另外一箇中止標準,網絡的訓練就會中止。

with tf.Session() as sess:
    # 初始化全部變量
    sess.run(tf.global_variables_initializer())

    for e in range(epochs):
        # 將數據打亂
        shuffle_indices = np.random.permutation(np.arange(y_train.shape[0]))
        X_train = X_train[shuffle_indices]
        y_train = y_train[shuffle_indices]

        for i in range(y_train.shape[0] // batch_size):
            start = i * batch_size
            batch_x = X_train[start : start + batch_size]
            batch_y = y_train[start : start + batch_size]
            sess.run(optimizer, feed_dict={X: batch_x, Y: batch_y})

            if i % 50 == 0:
                print('MSE Train:', sess.run(loss, feed_dict={X: X_train, Y: y_train}))
                print('MSE Test:', sess.run(loss, feed_dict={X: X_test, Y: y_test}))
                y_pred = sess.run(out, feed_dict={X: X_test})
                y_pred = np.squeeze(y_pred)
                plt.plot(y_test, label='test')
                plt.plot(y_pred, label='pred')
                plt.title('Epoch ' + str(e) + ', Batch ' + str(i))
                plt.legend()
                plt.show()
複製代碼

運行結果爲:

MSE Train: 9.56518e-05
MSE Test: 0.0025863606
MSE Train: 6.0618047e-05
MSE Test: 0.0025002975
MSE Train: 0.00014856807
MSE Test: 0.0017371146
MSE Train: 0.00016200903
MSE Test: 0.0025396077
MSE Train: 0.00010259051
MSE Test: 0.0030134947
MSE Train: 7.979905e-05
MSE Test: 0.0023832247
MSE Train: 5.92488e-05
MSE Test: 0.0032762515
MSE Train: 8.747634e-05
MSE Test: 0.004848172
MSE Train: 8.5051965e-05
MSE Test: 0.0032768336
複製代碼

最後測試集的loss在0.003左右,能夠說是比較精確了。

可視化訓練結果:

20190226203532

有不少方法能夠進一步改善這一結果:增長隱藏層和改進神經元的設計,選擇不一樣的初始化和激活方案,提早中止等等。 此外,不一樣類型的深度學習模型,例如循環神經網絡,能夠在此任務上實現更好的性能。 可是,這不是這篇介紹性文章的範圍。有興趣的小夥伴能夠自行查找資料。

結論

正如開頭所說,股票的價格會受到經濟環境、政府政策、人爲操做多種複雜因素的影響,真正想要預測股市走向單靠這篇文章裏面所敘述的遠遠不夠,本文旨在結合時下熱點進行一次有關TensorFlow的技術推薦。

TensorFlow的發佈是深度學習研究中的一個里程碑事件。做爲一個學生,筆者也在積極的學習中,有興趣學習的小夥伴能夠在公衆號後臺(就是文末的那個公衆號)回覆「TensorFlow視頻」獲取一份質量較高的TensorFlow視頻,也能夠添加個人微信一塊兒交流進步。

完整源碼可在微信公衆號:「01二進制」後臺回覆:「股市分析」獲取

參考資料


「萬水千山都是情,給個關注行不行👇」

相關文章
相關標籤/搜索