使用概率編程和Pyro進行財務預測
本文為 AI 研習社編譯的技術博客,原標題 :
Financial forecasting with probabilistic programming and Pyro
作者 |Alexandr Honchar
翻譯 | 胡瑛皓校對 | 醬番梨
審核 | 約翰遜·李加薪 整理 | 立魚王
https://medium.com/@alexrachnog/financial-forecasting-with-probabilistic-programming-and-pyro-db68ab1a1dba
圖片來源 https://jmhl.org/research/
大家好,我回來了!去年我發表了幾篇利用神經網路做金融預測的教程,其中一些結果是有趣的,我覺得值得應用於真實交易應用中。如果你讀過那些文章,你可能注意到,當你用某些機器學習模型擬合「隨機」數據,並試圖找到其中隱含模式時,通常會陷於過擬合。我們用了不同的正則化技術以及額外的數據試圖解決這一問題,但這很費時且需要盲目搜索。
今天我會用略微不同的方法擬合之前的演算法。從概率角度進行處理,通過數據本身進行正則化,估計預測的確定性,使用較少的數據,將概率依賴引入到模型中。這裡主要講概況,我會更注重於應用問題,而不會特別深入的講解貝葉斯模型或變分推斷技術或數學細節問題。你可以在這裡找到代碼。
同時我也推薦你讀一下此前寫的利用神經網路做金融預測的教程:
Simple time series forecasting (and mistakes done)
Correct 1D time series forecasting backtesting
Multivariate time series forecasting
Volatility forecasting and custom losses
Multitask and multimodal learning
Hyperparameters optimization
Enhancing classical strategies with neural nets
Probabilistic programming and Pyro forecasts
Backtesting in Pandas
Pattern recognition and machine learning
Bayesian methods for hackers
可以看以下以下Python庫及相關文檔:
PyMC3
Edward
Pyro
概率編程
這裡的概率指什麼,為什麼稱之為編程? 首先我們回憶一下「正常的」神經網路及其輸出。神經網路帶有參數(權重),這些是以矩陣形式表示的,神經網路的輸出通常是一些標量值或向量(例如做分類時)。當模型訓練完成後,比如說使用SGD進行訓練,得到一些固定的權重矩陣,網路對於相同的樣本會輸出相同的結果。沒錯!那麼如果把參數和輸出看做相互依賴的分布會怎麼樣呢?神經網路里每個權重可以看做某個分布的樣本,同樣輸出可以看做全網路作為分布的一個樣本,這個分布依賴於網路中所有參數。這告訴我們什麼?
我們從最基本的開始說。如果把網路看做一組相互依賴的分布,它首先是一個聯合分布 p(y, z|x), 這裡y是輸出、z是模型「內部的」潛變數,依賴於輸入 x (常規神經網路都可以這樣看)。有趣的是這樣的神經網路分布,可以看做從 y ~ p(y|x) 採樣,然後把輸出作為其分布(其中輸出通常是該分布的樣本期望,其標準差?—?—作為不確定性的估計?—?—分布的尾部越大——輸出的置信度越低)。
有了這樣的設定就後面理解略微清晰了點,我們只需要記得,從現在開始模型中所有的參數、輸入和輸出都是分布。當我們訓練模型時,需要擬合這些分布的參數,在實際任務中獲得更高的精度。這裡我們還需要知道,參數分布的形態是由我們來設定的 (開始時所有權重都初始化為 w ~ Normal(0, 1)分布,此後通過訓練獲得正確的均值和方差)。最初的分布是先驗分布,經過訓練以後的分布是後驗分布。我們用後者去採樣獲得輸出。
圖片來源http://www.indiana.edu/~kruschke/BMLR/
模型擬合是怎麼做的? 通用框架叫做變分推斷。如果不看細節我們可以假定,需要找到一個模型最大化對數似然 p_w(z|x), 這裡w是模型參數 (分布的參數), z 是潛變數 (隱神經元的輸出, 採樣自參數w的分布) ,x是輸入樣本數據。我們的模型就是這樣的。在Pyro可引入這樣一個實體作為該模型的guide,其中包含所有潛變數的分布q_ф(z), 此處 ф 稱為變分參數。這個分布必須近似「實際」模型參數的分布,也就是最好的擬合輸入數據。
訓練目標是最小化[log(p_w(z|x))?—?log(q_ф(z))] 關於輸入數據和guide樣本的期望。這裡不會過多介紹訓練的細節,因為可能涉及好幾門大學課程,現在把這個看做黑盒優化就好。
好的 那為什麼稱為編程? 通常這樣的統計模型(神經網路)被描述為從一個變數到另一個變數的有向圖, 這樣直接顯示變數的依賴:
圖片來源 http://kentonmurray.com/
最初概率編程語言被用於定義諸如這樣的模型並以此進行推斷。
使用概率編程的原因
從數據中學習它作為額外的潛變數,而不是傳統的在模型中使用dropouts或L1正則化。考慮到所有權重都是分布,可以從那裡採樣N次並得到輸出的分布,這裡可以看一下標準差估計一下模型輸出結果的置信度。這種方法的好處是,我們只需要較少的訓練數據並可靈活的在變數間增加依賴。
不使用概率編程的原因
我在貝葉斯模型使用尚沒有積累大量的經驗,不過在使用Pyro和PyMC3的過程中我發現,訓練過程很長且難以確定先驗概率。另外處理生產環境的樣本分布可能導致誤解和模稜兩可的情況。
數據準備
我從網上獲取每日以太幣的牌價等數據,其中包括OHLCV (開盤、最高、最低、收盤、成交量) ,另外還獲取了每天涉及以太幣的推特數量。這裡選取7天價格、成交量和推特數的換算為變動%,預測下一個交易日的變動。
價格 推特數和成交量變動
上圖為採樣的數據?—藍色表示價格變動, 黃色表示推特數變動,綠色是成交量變動。這些變數之間存在一些正相關(大概0.1–0.2之間), 所以我們可利用數據中的模式來訓練我們的模型。
貝葉斯線性回歸
首先我想看一下簡單線性回歸效果如何(直接從Pyro教程複製結果). 下面定義PyTorch模型 (官方教程里有各個詳細的說明):
這是一個簡單的確定性模型和之前一樣, 不過這就是在Pyro中定義概率模型的方式:
在上面的代碼中我們看到, 用W和b作為廣義線性回歸模型分布的參數,它們服從~Normal(0, 1)分布,這裡命名為prior。構造Pyro隨機函數(PyTorch里用RegressionModel), 賦值prior ({『linear.weight』: w_prior, 『linear.bias』: b_prior}) 基於輸入數據x從 p(y|x) 採樣。
模型的guide函數定義如下:
接下來為需要訓練的分布定義變分分布。可以看到,定義的W和b分布的形狀是一致的。為了更符合現實 (根據我們的假定),在本例中將分布收窄一些 (~Normal(0, 0.1))。
接下來訓練模型:
擬合後從模型中採樣y,重複100次,檢查預測的均值和標準差 (標準差越高, 本次預測的置信度越低).
在金融場景中預測中經典的指標是MSE, MAE 或 MAPE,這裡麻煩?—?—?相對誤差率較小並不等於模型效果就好,還需要檢查那些樣本以外的數據在模型中的效果並繪製成圖:
貝葉斯模型30天預測
看起來不太理想,不過最後那跳的形狀還不錯,我們繼續!
普通神經網路
這裡嘗試用以下這個簡單神經網路得到一些有趣的特性,首先我們構造一個MLP,隱層含有25神經元後面跟著線性激活函數:
訓練100個epoch:
以下是訓練結果:
Keras 神經網路預測30天預測
結果不如簡單貝葉斯回歸,此外模型給不出確定性估計,更重要的是模型也不是正則化的。
貝葉斯神經網路
現在把剛才用Keras定義的神經網路用PyTorch框架改寫一下:
對比貝葉斯回歸模型,現在有2組參數 (輸入到隱層以及隱層到輸出),這裡我們稍微修改一下模型先驗:
以及分布:
需要給模型中所有分布設定不同的名字,因為此處不能有模稜兩可或重複! 代碼中可以看到更多細節。我們看一下模型擬合後採樣的最終結果:
Pyro神經網路30天預測
看起來比之前所有的結果都要好一些!
關於正則化或者說貝葉斯模型得到的權重比之普通模型,要看一下權重的統計值。可以這樣檢查Pyro模型的參數:
在Keras 模型中是這麼查看的:
輸入和隱層之間部分權重
事實上有趣的是,均值方差變小了,權重也變得稀疏。令人驚奇的是,最終學習得到一個稀疏表示第一組類似L1正則化,第二組類似L2正則化。可以跑一下代碼 !
結論
我們使用新的方法訓練神經網路,通過更新權重的分布(而不是依次更新靜態權重),得到了有趣的並有前景的結果。我想強調貝葉斯方法可以幫助我們在不手工添加正則化器的情況下正則化神經網路,幫助理解模型的不確定性,並通過較少數據得到較好的訓練結果。敬請關注!
P.S.請關注我Facebook 賬號,上面會寫一些 AI 短文, 還有我個人Instagram 和 Linkedin號!
※僅開放一天,已有 16 支隊伍成功擊敗 OpenAI Five
※AI 的偏差,取決於人們如何使用機器學習系統
TAG:AI研習社 |