比特幣突破8000美元,我們找到了用DL預測虛擬貨幣價格的方法

 2017-11-22 12:08:00.0

原標題:比特幣突破8000美元,我們找到了用DL預測虛擬貨幣價格的方法

選自GitHub

作者:David Sheehan

截至 11 月 22 日,比特幣的價格再創歷史新高(約 1 比特幣兌 8120 美元),在驚訝於虛擬貨幣「不可戰勝」的同時,我們或許能可以從這一波熱潮中學到些什麼。本文中,博士畢業於倫敦大學學院(UCL)的 David Sheehan 爲我們介紹了使用 Keras 基於 LSTM 預測比特幣價格走勢的詳細方法。在測試中,這個機器學習預測法似乎有着不錯的準確度。

如果要列出 2017 年最爲荒謬的三樣事物,則一定是指尖陀螺、人工智能,當然,還有加密虛擬貨幣(cryptocurrency)。以上是玩笑話,實際上我對虛擬貨幣的原理印象深刻,而且非常看好這種顛覆性技術的長期前景。我試圖通過深度學習、機器學習或者說人工智能(是的,所有這三個!)成功預測虛擬貨幣的價格。

我認爲把深度學習和虛擬貨幣結合起來是非常獨特的想法,但是在寫本文時,我發現了一些類似的內容(http://www.jakob-aungiers.com/articles/a/Multidimensional-LSTM-Networks-to-Predict-Bitcoin-Price)。這篇文章只關注比特幣(最有名的虛擬貨幣),但是我還想討論一下以太幣。

我們打算使用 LSTM 模型,一種非常適合時序數據的深度學習模型。如果你希望真正瞭解理論或概念,那麼推薦閱讀:

    • 完整代碼地址:https://github.com/dashee87/blogs/blob/master/Jupyter/2017-11-20-predicting-cryptocurrency-prices-with-deep-learning.ipynb

    數據

    在構建模型之前,我們需要先獲取一些數據。Kaggle 上的數據集(https://www.kaggle.com/mczielinski/bitcoin-historical-data)非常詳細地記錄了近幾年的比特幣價格。在這個時間長度(數年)中,噪聲可能蓋住了信號,因此我們需要選擇單日價格數據。問題在於我們可能沒有充足的數據(我們需要數百行而不是數千行、數百萬行)。在深度學習中,沒有模型可以克服數據嚴重缺乏的問題。我同樣不想使用靜態文件,因爲未來使用新數據更新模型時,這種做法會複雜化更新流程。於是,我們計劃從網站和 API 中抓取數據。

    我們將在一個模型中使用多種虛擬貨幣,因此從同一個數據源抓取數據或許是一個不錯的主意。我們將使用 coinmarketcap.com。現在,我們只需要考慮比特幣和以太幣,但是使用這種方法添加最新火起來的山寨幣(altcoin)就很難了。在輸入數據之前,我們必須加載一些 Python 包,這樣會容易一些。

    1. importpandas aspd

    2. importtime

    3. importseaborn assns

    4. importmatplotlib.pyplot asplt

    5. importdatetime

    6. importnumpy asnp

    7. # get market info for bitcoin from the start of 2016 to the current day

    8. bitcoin_market_info =pd.read_html("https://coinmarketcap.com/currencies/bitcoin/historical-data/?start=20130428&end="+time.strftime("%Y%m%d"))[0]

    9. # convert the date string to the correct date format

    10. bitcoin_market_info =bitcoin_market_info.assign(Date=pd.to_datetime(bitcoin_market_info['Date']))

    11. # when Volume is equal to '-' convert it to 0

    12. bitcoin_market_info.loc[bitcoin_market_info['Volume']=="-",'Volume']=0

    13. # convert to int

    14. bitcoin_market_info['Volume']=bitcoin_market_info['Volume'].astype('int64')

    15. # look at the first few rows

    16. bitcoin_market_info.head()

    以上代碼的解釋是,我們加載了一些 Python 包,然後導入這個網站(https://coinmarketcap.com/currencies/bitcoin/historical-data/)中的表格。經過少量的數據清理操作,我們獲得了上面的表格。我用同樣的操作爲以太幣也製作了一個表格,只需要把 url 中的『bitcoin』替換爲『ethereum』就可以了(代碼省略)。

    爲了證明數據是準確的,我們將兩種虛擬幣的價格和成交量按時間作圖:

    訓練、測試和隨機遊走

    有了數據,接下來就該建立模型了。深度學習中,通常把數據分爲訓練集和測試集。模型建立在訓練集上,隨後用未見過的測試集評估。在時間序列模型中,我們通常使用一段時期的數據訓練,然後用另一段時期的數據進行測試。我把時間界限定爲 2017 年 6 月 1 日(即模型將使用該日期之前的數據進行訓練,用該日期之後的數據進行測試)。

    從上圖可知,大部分的訓練時期內虛擬貨幣都是相對更低價的。因此,訓練數據可能對於測試數據來說沒有代表性,這會削弱模型泛化到未知數據上的能力。不過請先保持樂觀,在實際應用我們的深度模型之前,討論一下更簡單的模型也是有意義的。最基礎的模型是設定明天的價格等於今天的價格(可以簡單粗暴地稱之爲滯後模型,lag model),數學公式:

    通過擴展滯後模型,我們一般會使用隨機遊走(random walk)算法擬合股票價格,用數學公式定義即:

    我們將從訓練集中確定 μ 和 σ,然後將隨機遊走模型應用到比特幣和以太幣測試集上。

    結果很不錯!除了一些缺陷,該模型基本上追蹤到了兩種貨幣的實際收盤價。它甚至捕捉到了六月中旬和八月下旬的以太幣價格上升(和隨後的下跌)。正如在其他博客中提到的,由於誤差無法傳遞到隨後的預測中,單點預測的模型通常是有誤導性的。由於將真實價格饋送到模型中,無論誤差有多大,都會在下一個時間點被重新設置。比特幣隨機遊走其實特別具欺騙性,因爲 y 軸的分佈範圍很寬,才使得預測線看起來很平滑。

    不幸的是,使用單點預測評估時間序列模型很普遍。使用多點預測測量準確率可能會更好,用這種方法,之前預測的誤差不會被重設,而會組合到後續的預測中。因此,性能較差的模型將得到更多的懲罰。用數學公式定義即:

    接下來我會使用隨機遊走模型對整個測試集進行預測。

    模型的預測對隨機種子非常敏感。我選擇了一個隨機種子,其中整個區間內的隨機遊走對於 Ethereum 來說幾乎都是降低的。在相應的 Jupyter notebook 完整代碼中,你可以交互地控制種子的值,看看它表現的有多糟糕,如下圖所示:

    注意單點隨機遊走看起來多麼準確,即使其背後沒有任何實質性內容。幸運的是,你會對任何聲稱能夠準確預測價格的文章持懷疑態度的。

    長短期記憶(LSTM)

    如果讀者對 LSTM 的理論比較感興趣,可以查看上文我們發過的教程與解釋。在本文中,我們並不需要從頭構建一個 LSTM 網絡,我們甚至都不需要理解它就能通過如 Keras 或 PyTorch 那樣的深度學習框架完成實現。本文選擇的是 Keras 框架,因爲它只需要很少的理論知識,並且是目前最直觀的深度學習框架。

    我創建了一個稱之爲 model_data 的數據框架,我們刪除了前面的一些列(開盤價格、日最高價和最低價),並重新制定一些新的列。close_off_high 列表示收盤價與日最高價之間的距離,-1 和 1 分別表示收盤價等於日最低或日最高價。volatility 列表示日最高價與最低價之間的差除以開盤價。model_data 按從早到晚的順序排列,因此實際上我們並不需要日期列,所以這些信息並不會輸入到模型中。

    我們的 LSTM 模型將使用前面的數據(Bitcoin 和 eth)來預測特定虛擬貨幣第二天的收盤價格。我們必須確定模型能訪問之前多少天的數據,這裏簡單地設置爲 10,當然該超參數還能進一步優化。因此我們構建了一個由連續 10 天數據(即窗口)組成的小數據框,即第一個窗口(window)將由訓練集中 0-9 行數據組成,第二個窗口由 1-10 行數據組成等。選擇較小的窗口規模意味着我們的模型可以使用更多的窗口,但缺點是模型沒有足夠的信息檢測複雜的長期行爲。

    深度學習模型對輸入的格式要求比較高,而原數據中有一些列的值範圍非常廣,可能取值範圍能達到數百萬的量級。所以首先我們就需要歸一化這些數據,因此每一個特徵的取值都會服從均值爲 0、方差爲 1 的屬性。一般來說,我們會令取值處於-1 到 1 之間,off_high 和 volatility 列基本已經符合條件,剩下的特徵可以使用歸一化方法。

    這個表格代表我們的 LSTM 模型輸入數據的一個樣本,這 10 條數據可以組成一個窗口,並且我們總共有數百個類似的窗口。我們已經歸一化了一些列以令它們的值在第一個時間點等於 0,所以我們的目標是預測該時間點的價格變化。我們現在已經準備建立 LSTM 模型了,Keras 貫序模型非常簡單,我們只需要將不同的層級疊加在一起就行了。

    1. # import the relevant Keras modules

    2. fromkeras.models importSequential

    3. fromkeras.layers importActivation,Dense

    4. fromkeras.layers importLSTM

    5. fromkeras.layers importDropout

    6. defbuild_model(inputs,output_size,neurons,activ_func ="linear",

    7. dropout =0.25,loss="mae",optimizer="adam"):

    8. model =Sequential()

    9. model.add(LSTM(neurons,input_shape=(inputs.shape[1],inputs.shape[2])))

    10. model.add(Dropout(dropout))

    11. model.add(Dense(units=output_size))

    12. model.add(Activation(activ_func))

    13. model.compile(loss=loss,optimizer=optimizer)

    14. returnmodel

    那麼,build_model 函數構建了一個模型,名爲 model(model= Sequential),該模型添加了一個 LSTM 層和全連接層。該層的形態已經調整以適合輸入(n x m 的矩陣,n 和 m 分別代表時間點/行和列)。該函數還包括更通用的神經網絡特徵,如 dropout 和激活函數。現在,我們只需指定 LSTM 層中神經元的數量(我選擇了 20 個以保證合理的運行時)和訓練數據。

    1. # random seed for reproducibility

    2. np.random.seed(202)

    3. # initialise model architecture

    4. eth_model =build_model(LSTM_training_inputs,output_size=1,neurons =20)

    5. # model output is next price normalised to 10th previous closing price

    6. LSTM_training_outputs =(training_set['eth_Close'][window_len:].values/training_set['eth_Close'][:-window_len].values)-1

    7. # train model on data

    8. # note: eth_history contains information on the training error per epoch

    9. eth_history =eth_model.fit(LSTM_training_inputs,LSTM_training_outputs,

    10. epochs=50,batch_size=1,verbose=2,shuffle=True)

    11. #eth_preds = np.loadtxt('eth_preds.txt')

    12. --------------------------------------------------------------------------

    13. Epoch50/50

    14. 6s-loss:0.0625

    我們剛纔構建了一個 LSTM 模型來預測明天的以太幣收盤價。現在我們來看一下效果如何。首先檢查訓練集性能(2017 年 7 月之前的數據)。代碼下面的數字代表 50 次訓練迭代後該模型在訓練集上的平均絕對誤差。我們可以看到模型輸出就是每日收盤價。

    我們不應對它的準確率感到驚訝。該模型可以檢測誤差來源並進行調整。事實上,獲取趨近於零的訓練誤差並不難。我們只需要數百個神經元和數千個訓練 epoch。我們應該對它在測試集上的性能更感興趣,因爲測試集中是模型未見過的全新數據。

    注意單點預測具備誤導性,而我們的 LSTM 模型似乎可以在未見過的測試集上實現良好的性能。最顯著的缺點是單點預測無法檢測出當以太幣突然上漲時必然會下跌(如六月中和十月)。事實上,它一直都是失敗的,只不過在這些波動點更加明顯而已。預測價格一般更接近一天後的實際價格(如七月中的下跌)。我們還可以構建一個適用於比特幣的類似的 LSTM 模型,測試集預測結果見下圖(完整代碼見上文地址)。

    如前所述,單點預測具有一定誤導性。我們現在構建一個 LSTM 模型來預測接下來 5 天的虛擬貨幣價格。

    從視覺效果上來看,預測結果沒有其單點預測更加鮮明。但是,我很高興,該模型返回了一些細微的行爲(如以太幣圖的第二條線);它不僅僅預測價格在一個方向的移動軌跡。因此,該模型還有很多優化空間。

    現在回到單點預測,我們的深度機器人工神經模型看起來還不錯,但是隨機遊走模型看起來也還行。與隨機遊走模型類似,LSTM 模型對隨機種子的選擇很敏感(模型權重最初是隨機分配的)。那麼,如果我們想對比這兩種模型,就需要把每個模型運行多次(比如,25 次)來評估模型誤差。誤差可以作爲測試集中真實和預測收盤價的絕對差。

    或許 AI 完全值得這些炒作!這些圖顯示了在進行 25 次不同的初始化之後,每個模型在測試集上的誤差。LSTM 模型對比特幣和以太幣價格的預測誤差分別是 0.04 和 0.05,完勝相應的隨機遊走模型。

    只是爲了打敗隨機遊走模型的話也太 low 了。對比 LSTM 模型和更合適的時序模型(加權平均值,ARIMA 或 Facebook 的 Prophet)豈不是更加有趣!另外,我確定很難再提升我們的 LSTM 模型了(添加更多層和/或神經元,改變批量大小、學習率等)。可能虛擬貨幣價格變化沒有規律吧,可能沒有一個模型可以把信號和噪聲分離開(類似於使用深度學習預測地震的優點)。以後的文章中可能會討論這些話題。

    幸運的是,你已經察覺到我對使用深度學習預測虛擬貨幣價格變化的懷疑態度。原因在於我們忽略了最優的框架:人類智能。很明顯,預測虛擬貨幣價格的完美模型是:

    我確定他們最終最終會找到深度學習的使用案例的。同時,你可以下載完整的 Python 代碼構建自己的模型。

    原文鏈接:https://dashee87.github.io/deep%20learning/python/predicting-cryptocurrency-prices-with-deep-learning/

    文章來源:機器之心