做者:chen_h
微信號 & QQ:862251340
微信公衆號:coderpai
個人博客:請點擊這裏git
本文的代碼請點擊這裏。Talk is cheap, show me the code.github
在過去的幾個月中,我對深度學習很是着迷,特別是它在天然語言處理中的應用。個人大部分職業生涯都是在金融領域度過的,特別是在算法交易和交易數據替換方面。算法
我寫這篇文章的想法直接來自個人工做經驗。我做爲一名「深度學習」的愛好者時,對於深度學習我沒有很深刻的瞭解。可是我但願個人理解能夠表達到位,而且能夠幫助到你。sass
在不少的 NLP 問題中,咱們最終會把序列編碼成一個固定大小的表示,而後將這個編碼再解碼成另外一個序列。例如,咱們可能會在文本中進行實體標記,從英文翻譯成法語,或將音頻轉換成文本。在這些領域都出現了大量的工做,而且不少成果都取得了最早進的表現。bash
在我看來,NLP 與金融數據分析之間的最大不一樣在於,語言有必定的結構性,雖然這個結構性比較模糊難懂。另外一方面,金融市場數據多是沒有任何結構能夠學習的。微信
在這個文章中,咱們假設金融市場數據是存在結構性的,固然這個假設多是不成立的,咱們這個文章可能也會直接推翻這個假設。咱們按照 NLP 的語義編碼模型來類比這個市場結構,若是你以爲這個想法沒有意義,那麼請閱讀下去,我相信你會以爲會有意義的。網絡
詞向量的模型有不少的,Richard Socher 的講座是一個很是好的教程。簡而言之,咱們能夠用語言模型來描述全部的單詞,而且在座標圖中進行顯示,而且利用幾何圖形來捕捉單詞之間的關聯性。有一個經典的例子是 「King - man + woman = Queen」 ,或者相似別的例子。架構
詞嵌入是很是酷的一個應用,由於咱們能夠利用一個很濃縮的方式來表示一個詞信息。比較傳統的詞嵌入方法是構建一個包含全部單詞的詞表,若是當前詞是查詢詞,那麼該位置設置爲 1 ,其他設置爲 0 。可是這不是一個有效的方法,並且也沒有任何詞關聯意義。可是經過詞嵌入,咱們用一個固定維度的向量來表示一個單詞,而後利用更高維度的幾何特性來尋找詞之間的關聯性。函數
下圖展現了一個例子。詞向量的模型是須要一個大型的語料庫進行訓練。通過幾天的高密度訓練,每一個詞都會獲得一個高維度的詞向量。這個「空間」向量會有相似於「距離」的概念,因此咱們能夠計算哪些詞是互相接近的。該方法的做者舉了一個例子(就是下圖),用來計算跟 post
可是除了詞,咱們對別的事物也能夠進行高維度的編碼,好比咱們接下來要介紹的金融市場數據。
第一個我據說的詞嵌入算法是 word2vec 。我想在金融市場數據上面獲得相同的效果,雖然我會使用一些比較不一樣於 word2vec 的算法。個人輸入數據是 csv 格式的。第一類表示日期,另外的 4*1000 列對應於 1000 只股票的高低開倉價。那麼,咱們的輸入向量就是 4000 維度的,這個維度太大了。因此,咱們第一件事就是把這個高維度的向量壓縮到一個低維度的向量,好比說 300 維度(由於咱們喜歡這個電影 ^_^)。
若是你以爲把一個 4000 維度的向量壓縮到 300 維度是一件很難的事,那麼你就大錯特錯了。其實這很簡單,咱們只須要乘以一個矩陣,矩陣就至關於一個巨大的 excel 表格,每一個單元格中都會有一個數字,而且不存在任何的格式。想象一下,咱們有一個 4000 列和 300 行的 excel 表格,咱們把這個表格與上面的 4000 維度向量進行相乘,那麼咱們就能夠獲得一個 300 維度的向量。這個就是最基礎的線性代數知識,你確定能明白。
那麼,如今的難點就是如何去設置這個巨大的表格矩陣,「深度學習」 就是用在這個矩陣的初始化和更新上面。最終,這個電子表格矩陣將會是一個不錯的轉移矩陣,能夠將咱們的 4000 維度向量轉換成一個簡潔的 300 維度向量。
接下來,咱們要作一些比較神奇的事,那就是激活函數。咱們要給每個值加上一個激活函數。將這個激活函數添加到每個值上面,將每一個值的大小歸到 0 到 1 之間。那麼,爲何這樣作可使得咱們的向量更加特別,能夠學習和理解更加複雜的事。你能夠點擊這裏進行學習。
那麼接下來咱們須要處理的重要的事就是如何去找到這個轉移矩陣,使得咱們能夠損失更少的信息,將高維的股票向量轉換成低維的股票向量。咱們但願能利用這個向量來挖掘各個股票之間的相關性,也許咱們會發現當某個行業下滑時,另外一個行業的股票也會下滑。固然,咱們可能也會發現一些別的特徵,我認爲這對咱們未來的研究會很是有用。
讓咱們先把股票向量放在一邊,來談談語言模型。Andrej Karpathy 寫了一篇很流行的文章
。若是咱們學習莎士比亞的做品,而後一個字一個字的進行學習。那麼咱們能夠深度學習來學習一種語言模型。
在這種狀況下,語言模型是一個魔術盒。你能夠提供一句話的前面幾個字符,模型就會告訴你下一個字符是什麼。
若是咱們把語言模型的預測結果從新輸入到語言模型,那麼咱們模型將永遠運行下去。
而後這個模型會產生一大堆看起來像莎士比亞風格的文字。而後,咱們也能夠將這個思想用在 Linux 源碼上面,而後程序來產生代碼。或者,咱們能夠用在幾何代數課本上面,讓程序來產生內容。
這個魔術盒的實現機制咱們會在後續進行介紹,可是讓咱們先來假想一下,Karpathy 是利用前面的一些字符來預測下一個字符,那麼咱們是否能夠根據以前的市場向量,來預測下一個市場表現、市場向量或者別的東西,而這個預測模型就是這個魔術盒。咱們尚未決定咱們想要預測的是什麼,可是沒有關係,由於咱們不會將咱們的輸出反饋到咱們的輸入中。
因此,Karpathy 向咱們介紹了一些 Linux 例子的輸出,下面的代碼就是魔術盒的內容:
static void action_new_function(struct s_stat_info *wb)
{
unsigned long flags;
int lel_idx_bit = e->edd, *sys & ~((unsigned long) *FIRST_COMPAT);
buf[0] = 0xFFFFFFFF & (bit << 4);
min(inc, slist->bytes);
printk(KERN_WARNING "Memory allocated %02x/%02x, "
"original MLL instead\n"),
min(min(multi_run - s->len, max) * num_data_in),
frame_pos, sz + first_seg);
div_u64_w(val, inb_p);
spin_unlock(&disk->queue_lock);
mutex_unlock(&s->sock->mutex);
mutex_unlock(&func->mutex);
return disassemble(info->pending_bh);
}複製代碼
請注意,該魔術盒能夠知道如何去打開和關閉括號,而且能遵照程序的縮進約定,也就是函數代碼的正確縮進,多行 printk 語句也具備正確的內部縮進。這也就意味着這個魔術盒能夠理解代碼的遠程依賴關係,即魔術盒能夠聯繫到前面的代碼進行分析推敲。當它預測在 print 語句中時,它會知道它在一個 print 語句中,而且會記住它是在一個函數中(或者至少記住是在另外一個縮進範圍)中。太好了,這就很容易理解,具備捕捉細節和記住長期依賴關係的算法是很是有用的,由於咱們也是但願能在市場上找到長期的依賴關係。
那麼這個神奇的魔術盒裏面有什麼呢?它是一種被稱爲 LSTM 的循環神經網絡(RNN)。RNN 是一種深度學習算法,它擅長的是對序列進行操做(如字符序列)。在每一步,它對會對下一個字符進行預測,而且使用一個矩陣記性表示,就像咱們以前看到的那樣。由於 RNN 有一些內部的記憶,因此它能夠記住一些之前看到的東西。它會使用這個內部記憶來決定下一次輸入中應該如何操做。使用該內存記憶,RNN 能夠記住它在必定範圍內的內容,這就是咱們爲何能夠對輸入文本進行預測處理。
RNN 有一個很好的變體稱爲 LSTM,LSTM 巧妙的設計了 RNN 內部的記憶單元,這個單元能夠作如下事:
能夠選擇性的記住一些東西;
能夠選擇性的去忘記一些東西;
選擇應該輸出多少記憶內存;
因此,當一個 LSTM 看到一個 「{」 ,而且對本身說「這個很是重要,我應該把它記住」 。而當它這樣作時,它基本上就記住了這是一個嵌套的範圍。一旦看到相應的 「}」 ,它就會決定忘記原來的大括號,所以忘記它在一個嵌套的範圍內。
咱們能夠將幾個 LSTM 堆疊在一塊兒,這樣 LSTM 能夠學習到更多的抽象概念。如今,前一個 LSTM 的輸出變成了下一個 LSTM 的輸入,每一個 LSTM 會學習到更加抽象的數據。在上面的例子中(這個只是說明性的猜想解釋),第一層的 LSTM 可能會學習由空格分割的字符,下一層可能會學習像(static void action_new_function)這樣的字符類型,下一層可能會學習函數的概念以及參數等等。雖然 Karpathy 在博客中已經有很是好的說明例子了,可是要清楚的說明每一層的具體任務仍是很是苦難的。
你可能會注意到,Karpathy 使用字符做爲他模型的輸入,而不是詞嵌入(技術上是使用 0-1 編碼)。可是,Lars Eidnes 在
文章中使用詞嵌入來處理。上圖顯示了他使用的網絡。咱們先不考慮 softmax 部分(這部分咱們後續介紹),先來看看 LSTM 堆棧和模型的輸入部分。咱們發現模型的底部輸入是一系列的單詞向量(記住,一個詞向量表示的是一個單詞的語義)。Lars 輸入一個字向量序列,其中每個做用以下:
影響第一個 LSTM;
前一個 LSTM 的中間輸出做爲下一個 LSTM 的輸入;
前一個 LSTM 輸出的下一個字做爲下一個 LSTM 的輸入;
雖然咱們要作一樣的事情,可是可能有一點小小的區別,咱們不是把字向量做爲輸入,而是咱們的 Market2Vec ,這個市場向量就是咱們以前描述出來的。咱們來回顧一下,對於給定的時間點,咱們的 MarketVectors 應該包含在這個時間點發生的市場狀況的總和。經過 LSTM 的序列化,咱們但願可以捕捉到市場上發生的一個長期依賴關係。經過幾個 LSTM 的堆棧,咱們但願能夠獲得更高層次的市場行爲抽象數據。
在 Karpathy 的例子中,LSTM 的輸出是抽象的表示下一個字符的預測向量。在 Eidnes 的例子中,LSTM 是輸出下一個字符向量。這兩種狀況的下一步都是將一個抽象的事物表示成一個機率向量,這是一個機率列表,說明每一個字符或者單詞在下一個位置出現的可能性。這裏則是 softmax 函數在工做了,一旦咱們擁有了這個機率列表,咱們則須要選擇出最有可能出現的單詞或者字符。
當咱們處理「市場預測」的問題時,咱們須要問本身,咱們真正想要預測的是市場的什麼狀況?我這裏有一些本身的想法,你們能夠參考一下:
預測 1000 支股票中每一支股票接下來的價格變化;
預測在接下來的 n 分鐘內,一些指標(S&P,VIX等等)的變化;
預測在接下來的 n 分鐘內,哪些股票的價格將上漲超過 x%;
(我我的最喜歡的)預測哪些股票在接下來的 n 分鐘內,上漲/下跌 2x%,而這段時間內不會下跌/上漲超過 x% ;
(本文將會介紹的)預測在接下來的 n 分鐘,VIX 的值上漲/下跌 2x %,而這段時間內不會下跌/上漲超過 x%;
第一和第二個就是迴歸問題,咱們必須預測的是一個實際的數字而不是一個特定事件的機率(好比字符 n 出現或者市場上漲)。這個很是準確,可是不是我想作的事。
第三和第四是兩個很是類似的問題,他們都要求預測一個事件(技術術語,就是一個類標籤)。這個事件多是接下來出現字母是 n ,或者接下來10分鐘內某隻股票是否會上升 5%,而不會降低超過 3%。第三和第四之間的權衡關係是,第三個問題更加常見,所以更容易學習到,而第四個問題更加有價值,它不但對利潤有預測,並且對風險也有必定的約束。
第五個問題是咱們在這篇文章須要解決的,這個問題跟第三個和第四個問題很是相似,可是它更加容易一些,由於咱們有一些機制能夠遵循。VIX 指數被稱爲恐怖指數,它表明了 S&P 500 指數的股票波動。它是經過觀察指數中每一個股票的隱含波動率得出來的。
那麼咱們爲何會去預測 VIX 這個指數呢?緣由主要以下:
這只是一個數字,而不是 1000 支股票,這就使得咱們在算法設計上會更加簡單,計算成本也會下降不少;
這是多個股票的總結,因此跟大多數股票是相關的;
它不是單純的對咱們的輸入數據進行線性組合。隱含的波動率是從一個很是複雜的非線性公式中計算出來的,而 VIX 是基於這個波動率再進行推導得出來的。若是咱們能夠進行預測,那麼這將是一件很是酷的事。
這個是直接能夠用來指導交易的額,若是咱們真的能夠設計出一個有價值的網絡,那麼咱們就能夠直接在線上使用它。
在將來幾分鐘內,咱們如何使用以前的數據來預測 VIX 的變化呢?對於咱們數據集中的每個點,我會在 5 分鐘後再次看到該數據點的 VIX 變化。若是在那段時間內上升了超過 1%,可是沒有超過 0.5%。那麼,咱們的模型將輸出 1,不然就是輸出 0。而後咱們會獲得以下一系列的標籤:
0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0 ….複製代碼
咱們想利用以前壓縮的市場向量,而後輸入到 LSTM 模型中得出最終的機率結果,從技術上來分析,由於咱們最終只要輸出一個標籤,咱們也可使用 sigmoid 函數,可是若是咱們作二分類結果,仍是建議使用 softmax 函數。
因此,在咱們深刻分析這個算法應用以前,讓咱們先來回顧一下咱們已經學習了哪些內容:
咱們以 1000 支股票的價格做爲輸入數據;
數據序列中的每個時間點都是市場的一個快照反饋。咱們使用一個壓縮網絡,將輸入的 4000 維度壓縮到 300 維度;
如今咱們有一系列的股票市場向量,咱們把這些股票向量輸入堆棧 LSTM 中,而後按照每一個時間步驟來進行學習。LSTM 會記住一些市場以前的有效信息,這些信息會影響後續的市場反饋;
咱們將第一層 LSTM 的輸出傳遞到另外的 LSTM 結構。這些結構會記住一些更高層次的抽象信息;
最後,咱們會根據堆棧 LSTM 的最後輸出,利用 softmax 函數來獲得VIX 在接下來5分鐘內上漲 1%,而不降低 0.5%的具體股票;
如今是最有趣的部分。咱們如今所作的一切均可以被稱爲是一個前向的過程。當咱們訓練算法時,咱們也會去作以上的那些步驟,而後部署到生產環境中使用它。如今咱們須要討論的是一個反饋的過程,這個反饋是咱們須要在算法中進行學習的過程。
在訓練的過程當中,咱們不只準備了數年的歷史訓練數據,還手動準備了一系列的預測目標,0 和 1 都是咱們對歷史數據進行打的標籤。
爲了學習,咱們須要將市場數據輸入咱們的神經網絡,而且將網絡的輸出結果和咱們的標籤數據進行對比,最後獲得一個損失值,這個對比函數就是一個損失函數。在咱們的例子中這個對比比較簡單,咱們能夠將咱們的損失函數設計以下:
ERROR = (1/2)*(((precomputed)— (predicted probability))² )複製代碼
這就是一個損失函數。也就是說,咱們能夠去計算出深度學習模型的輸出值與準確值之間的偏差有多大。根據這些偏差,咱們能夠利用一些更新函數來更新一整個網絡的權重,從而獲得一個比較好的模型。
該更新過程會一直更新到模型的開始,因此模型會不斷的調整咱們的 MarketVectors 向量,以便咱們的 MarketVectors 能夠表示更多的信息。
LSTM 模型能夠選擇去記住哪些內容和忘記哪些內容,以便模型能夠分析那些與咱們任務最相關的量。
LSTM 模型還能夠學習數據的更加抽象表示,以便模型學習數據更多的特徵。
這一點是很是讓我吃驚的,由於深度學習能夠學習那麼多負責和抽象的東西。咱們從前都沒有接觸過這種模型。
對於這個項目我還有一些更加深刻的想法,一些我可能還會嘗試的想法,而且我認爲這些想法對實際項目時有用的。
通常來講,特定市場的流動性越高資金的利用效率越高。我認爲這是一個雞與蛋以前的循環,而市場變得更加的流動,它可以吸取更多的資本交易,而且資本收到的損害最小。隨着市場變得更加流動,更多的資本能夠在市場中使用,你會發現更多複雜的交易玩家會進入市場。
一個快速的推論是,在一個比較不流動的市場中,競爭並非那麼複雜,因此這樣的機制可能會帶來機會,我會在這樣的市場嘗試交易。
這些算法的知識和架構對計算機領域是比較陳舊的,可是在股票金融領域的應用是一個全新的應用。咱們假設一些頂級玩家已經在使用這些技術進行套利,而且可能已經很長一段時間了。可是正如我前面提到的,他們多是在一個流動性很大的市場進行套利工做,他們須要很大的市場資金規模,這樣才能去平攤他們的運營成本。我認爲,下一次的市場應用會在那些流動性比較小的市場,這些市場尚未被開發徹底,存在很大的套利空間。
雖然我在上面提到的是輸入一個單通道的數據流,但我認爲一個更加有效的訓練方法是在多個時間通道上面對市場數據進行訓練。也就是說,我目前採用的是 30 秒採樣一次,我但願網絡能夠解決幾個小時的數據依賴關係。
我不知道這個想法是否有意義,可是我認爲若是咱們能夠將計算成本下降到必定程度,那麼咱們能夠把多個時間點進行融合訓練。這個融合模型的訓練我還在思考中,目前有點困難。
當咱們在天然語言處理中,使用的詞向量模型都是在一個預訓練模型之上進行微調的。可是在咱們的狀況下,沒有一個預訓練好的市場向量可使用,也沒有一個明確的算法去進行訓練。
我原來的想法是使用一個自動編碼器來進行訓練,就好像這篇論文,可是端到端的訓練好像看起來更加酷。
更重要的考慮是,端到端的序列模型在機器翻譯領域已經比較成熟了,也就是說咱們能夠把一些文本編碼成一個向量,而且進行解碼。在這種觀點下,我所描述的整個架構本質上就是一個編碼器,可是我尚未真正的設計出一個解碼器。
可是,對於網絡的第一層,我想設計一個特殊層,即咱們須要把輸入的 4000 維度向量降維到一個 300 維度的向量。經過這些低維度的向量,咱們須要去找到各個股票之間的一些關聯度。
另外一個替代的方向是對每一個 LSTM 輸入一個數據,而後編碼成一個輸出向量。但我認爲這個多是無效的,由於各個數據模型之間的相關度會降低不少,而且這種方法會須要 10 倍的計算資源,比較浪費。可是從另外一方面來講,這種架構能夠多個 GPU 進行訓練,能夠提升一點速度。
最近,字符級的機器翻譯方面出現了不少的論文。這篇論文帶給了我不少的啓發,由於這篇文章試圖採用 CNN 來解決長距離的依賴關係,而不是 RNN 。我尚未深刻的去閱讀這篇論文,可是咱們能夠假想一下,咱們把每一個股票當作一個通道(相似於 RGB圖像的三個通道),而後把每一個通道輸入卷積模型中進行卷積操做,從而來捕捉市場的長期依賴信息。這種方法跟他們從字符級別上進行語義編碼的方式是相同的。
算法社區直播課:請點擊這裏
CoderPai 是一個專一於算法實戰的平臺,從基礎的算法到人工智能算法都有設計。若是你對算法實戰感興趣,請快快關注咱們吧。加入AI實戰微信羣,AI實戰QQ羣,ACM算法微信羣,ACM算法QQ羣。詳情請關注 「CoderPai」 微信號(coderpai)。