您的位置:首頁>科技>正文

用深度學習預測比特幣價格

Python部落(python.freelycode.com)組織翻譯, 禁止轉載, 歡迎轉發。

如果要數2017年三個最荒誕的流行時尚, 那一定非指尖陀螺, 人工智慧和數位加密貨幣(譯者注:以下統稱密幣)莫屬了。 玩笑歸玩笑, 密幣的底層概念確實是讓人印象非常深刻, 我個人對這種顛覆性的技術的長期前景是非常看好的。 指尖陀螺就算了吧。 其實我自己是沒有持有任何密幣的。 但是, 即使我沒有登月的船票, 至少我還能通過成功預測密幣的價格來參與到這場盛大的派對。

我原以為結合深度學習和密幣是一種全新的概念, 但是研究過程中我發現原來已經有人提出了很相似的概念。

不過那篇文章只提到了比特幣, 我這裡還會涉及到乙太幣。 而且乙太幣明顯是要優於比特幣的, 所以我這篇肯定要比那篇更好了:P

我們會用到LSTM(Long Short Term Memory)模型, 它是深度學習模型的一種, 主要適用於時間序列資料。 如果你真的想要理解它的底層的理論, 我推薦你去讀這些博客[1],[2]和這篇論文[3]。 這裡我無恥地想要吸引更多的非機器學習群眾, 所以我會讓代碼保持最簡。 如果你想要自己動手玩玩這些資料或者模型, 我有一個Jupyter(Python)的筆記在這裡[4]。 廢話少說, 我們開始吧!

資料

在構建模型之前, 我們得先去獲取一些資料。 在Kaggle上有比特幣過去幾年裡每分鐘價格的資料集。 但是在這樣的時間軸上, 雜訊會淹埋有用的信號,

所以我們只能選擇每天的價格。 但是這樣帶來的問題是我們沒有足夠的資料。 在深度學習裡, 沒有什麼模型能夠彌補資料量的不足。 而且我也不希望依賴於靜態的資料檔案, 因為這樣的話以後有了新的資料, 想要更新模型就會非常複雜。 綜合考慮, 我們還是從網站和API里拉取資料。

因為我們打算用用一個模型預測多重密幣的價格, 所以最好我們的資料是從同一個資料來源獲取的。 這裡我們使用coinmarketcap.com的數據。 目前, 我們只考慮比特幣和乙太幣, 但是用同樣的方法, 要把其它的密幣加進來也是很容易的。 在引入資料之前, 讓我們先載入幾個Python庫, 這會讓後續的工作輕鬆許多。

解釋一下剛剛發生了什麼, 我們載入了一些Python庫,

然後加入了網站上的表格資料, 做了一些資料清洗之後, 就得到了如上表格。 對於乙太幣, 只用將連結裡的"bitcoin"替換成"ethereum"就可以了。

為了證明資料是準確的, 我們可以作出這兩種密幣的價格和成交量隨時間變化的圖。

訓練集, 測試集以及隨機漫步

我們有了一些資料, 現在需要開始搭建模型了。 在深度學習裡, 一般將資料集分為訓練集和測試集。 先用訓練集來訓練模型, 然後用沒有見過的測試集來評估模型。 在時間序列模型裡, 我們通常用一段時間的資料集來訓練, 然後用另外一段時間的資料來測試。

這裡, 我就隨意地選取2017年六月一號作為分界線, 之前的資料作為訓練資料, 之後的資料作為測試資料。

你可以看到訓練期的價格相對便宜。 這樣的話, 訓練資料可能就不能代表測試資料, 從而降低了模型預測未知數據的能力。 在用深度學習模型之前, 我們先用一種簡單的模型。最基本的模型是把明天的價格跟今天的價格設為相等,我們暫且叫它延遲模型(lag model)。用數學公式來定義這個模型就是:PredPrice(t)=ActualPrice(t−1)。

因為股票價格經常被認為是一種隨機漫步,所以我們就用它來擴展基本的延遲模型,用數學公式來定義就是:PredPrice(t)=ActualPrice(t−1)∗ϵ,ϵ∼N(μ,σ)。

我們從訓練集中推算出μ和σ,然後將隨機漫步模型用到比特幣和乙太坊的測試集上。

哇!看看這預測的線條。除了少數幾個轉捩點,對這兩種幣它的預測都跟實際價格很接近。甚至乙太坊在七月中旬和八月底的上漲都被它預測到了。在那個時候,如果我發起一個我自己的代幣,相信ICO一定會大豐收。就像我在另一篇博客裡指出的,只預測未來一步的模型的精准度是有欺騙性的,因為它不會將錯誤資訊帶入到接下來的預測。不管錯誤多大,最終在每一點上都會被重置,就跟真正的價格差不多。比特幣的隨機漫步尤其具有欺騙性,因為y軸的範圍很大,使得預測線顯得很平滑。

不幸的是,在評估時間序列模型的時候,單點預測其實是很普遍的。稍微好一點的方法是用多點預測來衡量精確性。那樣的話,之前預測的錯誤不會在下一點馬上被重置,而是會被吸收到接下來的預測中。這樣,壞的模型受到的懲罰會更重。用數學公式來表示就是:PredPrice(t)=PredPrice(t−1)∗ϵ,ϵ∼N(μ,σ) & PredPrice(0)=Price(0)。

模型預測對隨機的種子的選擇極為敏感。我選擇了一個跟全程隨機漫步跟乙太坊資料非常接近的模型。在Jupyter notebook裡,你可以互動式的選擇種子的值,看看模型可以爛到什麼程度。

注意單點隨機漫步總是看上去很精確,雖然這背後沒什麼實質的東西。希望你對任何博客裡宣稱準確的預測多一點警惕。不過這種擔心可能是多餘的,因為比起密幣炫目的市場宣傳對粉絲的誘惑力,這根本不算什麼。

LSTM

我之前說過,如果你對LSTM背後的理論感興趣,我推薦你去讀[5], [6]和[7]。幸運的是,我們不需要從頭開始構建模型行,甚至都不用理解它。有許多的庫已經包含了各種深度學習演算法的標準實現,比如TensorFlow,Keras,PyTorch等等。我選擇Keras,因為我發現它對於非專業人員最直觀。如果你對Keras不熟,可以參考我之前的教程。

model_data.head

我創建了一個新的資料幀叫做model_data。而且我之前的一些列,如開盤價,每日最高價和最低價等去掉了,同時制定了一些新的列。close_off_high是收盤價和最高價的差的一種表示,-1和1分別代表當日最低價和最高價。volatility列就是最高價減去最低價除以開盤價。你可能注意到了,model_data是從前到後排列的。這樣我們其實就不需要日期了,因為模型並不需要輸入日期。

對於兩種密幣,我們的LSTM模型都是用之前一段時間的資料來預測下一天的收盤價。我們需要決定用之前多少天的資料,這裡,我就選10天了,沒什麼道理,就是選個整數。然後我們創建一系列連續10天的資料視窗,第一個是0到第9天,第二個是第1天到第10天,以此類推。選擇的時間視窗越短,我們就能給模型喂的資料越多,但是不好的是這樣模型就沒有足夠的資訊來探測到複雜的長期行為,如果它們存在的話。

深度學習模型不喜歡大範圍變化的輸入資料。我們的資料裡,有些值在-1到1之間,有些則是百萬級別。我們需要給這些資料轉化到差不多的量級。一般做法是讓值在-1到1之間。off_high和volatility列都還好。其它的列,我們都要做一些轉換處理。

這個表就是我們的LSTM模型的輸入的一個樣本了,我們會有幾百個類似的表。對於有些列,我們將它們的第一個時間點的值設為0,然後我們的目標就是預測跟這個時間點的相對變化價格。現在我們就準備好開始創建我們的LSTM模型了。用Keras其實這一步非常簡單,就是一步一步往模型上套。

這樣,build_model函數就構建了一個空的模型,沒有想像力的被稱為model,並且LSTM層已經加上了。這一層接收我們的輸入,n*m個表格,n代表時間點的個數,m代表表格數。這個函數還包含了更多的通用神經網路特徵,如dropout和activation functions。現在,我們只需要指定LSTM層的神經元數,我選20,這樣執行時間能比較合理,然後是模型訓練的輸入資料。

Epoch 50/50
6s - loss: 0.0625

我們已經建立好了一個可以預測明天的乙太坊收盤價的LSTM模型了。讓我們對它的表現拭目以待。我們先檢查一下它在訓練集上的表現。代碼下方的數字是在訓練集上50次反覆運算之後的模型平均絕對誤差(mae)。我們模型的輸出是每天收盤價而非相對變化量。

對於它的精確程度我們不必太吃驚。模型能夠找到誤差的源頭並且自動調整。事實上,就算要達到零誤差也不是難事。我們可以弄幾百個神經元,反覆運算個幾千次。這個過程就是過擬合,本質上是在預測噪音。我們更應該關注的是它在測試集上的表現,因為這個對於模型是新的資料。

不算單點預測的誤導性的話,我們的LSTM模型看上去在這些沒有見過的資料上表現的也很好。最明顯的一個缺陷是它沒有預測到乙太坊價格在六月中旬和十月的突然上漲。事實上這是一個固有的問題,只是在這些尖刺上表現得更明顯。預測的價格基本上就像是真實價格向後移動了一天。更重要的是,模型似乎系統性地對乙太坊的價值高估,基本上預測線一直是在實際價格線的上方。我猜測是因為訓練集時期的資料乙太坊增長的太過驚人,所以模型認為這種趨勢會持續。我們可以對比特幣也建立一個類似的LSTM模型,測試集上的預測資料在下圖中描繪出來了。

前面我已經提到,單點預測是有欺騙性的。更近距離的看,你會發現預測資料基本上就是之前資料的鏡像。我們炫酷的深度學習LSTM模型已經部分重現了一個自回歸模型。用數學公式來表示就是:PredPrice(t)=ϕ0+ϕ1∗Price(t−1)+…+ϕp∗Price(t−p)+ϵ(t), ϵ(t)∼N(0,σ)。

好消息是自回歸模型經常被用於時序任務,說明LSTM模型的方向是靠譜的。壞消息是這是浪費LSTM的能力,我們可以花更少的時間,建一個簡單的多的自回歸模型,也能達到差不多的效果。更複雜並不意味著就更精確。

可以看出來對比單點預測這裡的結果要差一些。無論如何,我對模型體現出的一些細微的行為還是很高興的,它沒有簡單的預測價格一致的向同一個方向移動。所以還是有一些可以樂觀的地方。

回到單點預測,我們的深度神經模型看上去還行,但是簡單的隨機漫步結果也不差。跟隨機漫步模型一樣,LSTM模型也會對隨機種子的選擇敏感。所以如果我們想要比較這兩種模型,我們會在每個模型上運行多次,來估算模型的誤差。這個誤差用實際收盤價和預測的收盤價在測試集上的差來計算。

也許AI的炒作是值得的!這些圖表現了兩個模型在25個不同的初始值下的誤差。LSTM模型在比特幣和乙太坊中平均誤差分別是0.04和0.05,碾壓隨機漫步模型。

以打敗隨機漫步為目標太low了。拿LSTM和其它的時序模型來比較會更有意思。另外一方面,要改進我們的LSTM模型也不是太難,比如逐漸增加更多的層次和神經元,改變每一批資料的規模大小,學習速度等。不過,希望你能覺察到我對用深度學習預測密幣的價格的一些懷疑。因為我們忽略了最好的框架:人類智慧。顯然,預測密幣的完美『模型』是:它會永遠上漲。

總結

我們收集了一些密幣資料,然後將它們喂給了我們超酷的深度機器學習模型LSTM。不幸的是,預測的結果跟簡單地延伸之前的的價格沒有多大區別。我們如何能讓模型學習更複雜的行為呢?

1. 改變損失函數。平均絕對誤差(MAE)不鼓勵冒險。而用平均誤差方差,LSTM模型就會對尖刺和波谷更看重。

2. 對保守的自回歸類的模型懲罰。這樣會刺激深度學習演算法去探索更冒險,更有趣的模型。但是說比做容易。

3. 得到更多,更好的資料。如果單純的用過去的價格不能夠很好的預測將來的價格,我們就需要加入其他的特徵,讓這種預測能力更加強大。這樣的話,LSTM模型就不會對過去的資料如此依賴,可能能解鎖更複雜的行為。這可能是最好也是最難的解決方案。

以上是正面的解讀,負面的解讀是密幣的價格其實根本沒有模型可以預測,不管你的層次有多深。就比如看2016年的比特幣和2017年年末比特幣的瘋狂。任何建立在2016年資料上的模型都不可能預測到2017年的變化。所以建議你就用自回歸模型吧,能省不少時間呢。

但是我相信深度學習一定能夠在某寫地方有用。同時,你可以在這裡[8]下載Python代碼,訓練你自己的LSTM模型。謝謝閱讀!

[4]: https://github.com/dashee87/blogScripts/blob/master/Jupyter/2017-11-20-predicting-cryptocurrency-prices-with-deep-learning.ipynb

[8]: https://github.com/dashee87/blogScripts/blob/master/Jupyter/2017-11-20-predicting-cryptocurrency-prices-with-deep-learning.ipynb

英文原文:https://dashee87.github.io/deep%20learning/python/predicting-cryptocurrency-prices-with-deep-learning/
譯者:桂浩晉 我們先用一種簡單的模型。最基本的模型是把明天的價格跟今天的價格設為相等,我們暫且叫它延遲模型(lag model)。用數學公式來定義這個模型就是:PredPrice(t)=ActualPrice(t−1)。

因為股票價格經常被認為是一種隨機漫步,所以我們就用它來擴展基本的延遲模型,用數學公式來定義就是:PredPrice(t)=ActualPrice(t−1)∗ϵ,ϵ∼N(μ,σ)。

我們從訓練集中推算出μ和σ,然後將隨機漫步模型用到比特幣和乙太坊的測試集上。

哇!看看這預測的線條。除了少數幾個轉捩點,對這兩種幣它的預測都跟實際價格很接近。甚至乙太坊在七月中旬和八月底的上漲都被它預測到了。在那個時候,如果我發起一個我自己的代幣,相信ICO一定會大豐收。就像我在另一篇博客裡指出的,只預測未來一步的模型的精准度是有欺騙性的,因為它不會將錯誤資訊帶入到接下來的預測。不管錯誤多大,最終在每一點上都會被重置,就跟真正的價格差不多。比特幣的隨機漫步尤其具有欺騙性,因為y軸的範圍很大,使得預測線顯得很平滑。

不幸的是,在評估時間序列模型的時候,單點預測其實是很普遍的。稍微好一點的方法是用多點預測來衡量精確性。那樣的話,之前預測的錯誤不會在下一點馬上被重置,而是會被吸收到接下來的預測中。這樣,壞的模型受到的懲罰會更重。用數學公式來表示就是:PredPrice(t)=PredPrice(t−1)∗ϵ,ϵ∼N(μ,σ) & PredPrice(0)=Price(0)。

模型預測對隨機的種子的選擇極為敏感。我選擇了一個跟全程隨機漫步跟乙太坊資料非常接近的模型。在Jupyter notebook裡,你可以互動式的選擇種子的值,看看模型可以爛到什麼程度。

注意單點隨機漫步總是看上去很精確,雖然這背後沒什麼實質的東西。希望你對任何博客裡宣稱準確的預測多一點警惕。不過這種擔心可能是多餘的,因為比起密幣炫目的市場宣傳對粉絲的誘惑力,這根本不算什麼。

LSTM

我之前說過,如果你對LSTM背後的理論感興趣,我推薦你去讀[5], [6]和[7]。幸運的是,我們不需要從頭開始構建模型行,甚至都不用理解它。有許多的庫已經包含了各種深度學習演算法的標準實現,比如TensorFlow,Keras,PyTorch等等。我選擇Keras,因為我發現它對於非專業人員最直觀。如果你對Keras不熟,可以參考我之前的教程。

model_data.head

我創建了一個新的資料幀叫做model_data。而且我之前的一些列,如開盤價,每日最高價和最低價等去掉了,同時制定了一些新的列。close_off_high是收盤價和最高價的差的一種表示,-1和1分別代表當日最低價和最高價。volatility列就是最高價減去最低價除以開盤價。你可能注意到了,model_data是從前到後排列的。這樣我們其實就不需要日期了,因為模型並不需要輸入日期。

對於兩種密幣,我們的LSTM模型都是用之前一段時間的資料來預測下一天的收盤價。我們需要決定用之前多少天的資料,這裡,我就選10天了,沒什麼道理,就是選個整數。然後我們創建一系列連續10天的資料視窗,第一個是0到第9天,第二個是第1天到第10天,以此類推。選擇的時間視窗越短,我們就能給模型喂的資料越多,但是不好的是這樣模型就沒有足夠的資訊來探測到複雜的長期行為,如果它們存在的話。

深度學習模型不喜歡大範圍變化的輸入資料。我們的資料裡,有些值在-1到1之間,有些則是百萬級別。我們需要給這些資料轉化到差不多的量級。一般做法是讓值在-1到1之間。off_high和volatility列都還好。其它的列,我們都要做一些轉換處理。

這個表就是我們的LSTM模型的輸入的一個樣本了,我們會有幾百個類似的表。對於有些列,我們將它們的第一個時間點的值設為0,然後我們的目標就是預測跟這個時間點的相對變化價格。現在我們就準備好開始創建我們的LSTM模型了。用Keras其實這一步非常簡單,就是一步一步往模型上套。

這樣,build_model函數就構建了一個空的模型,沒有想像力的被稱為model,並且LSTM層已經加上了。這一層接收我們的輸入,n*m個表格,n代表時間點的個數,m代表表格數。這個函數還包含了更多的通用神經網路特徵,如dropout和activation functions。現在,我們只需要指定LSTM層的神經元數,我選20,這樣執行時間能比較合理,然後是模型訓練的輸入資料。

Epoch 50/50
6s - loss: 0.0625

我們已經建立好了一個可以預測明天的乙太坊收盤價的LSTM模型了。讓我們對它的表現拭目以待。我們先檢查一下它在訓練集上的表現。代碼下方的數字是在訓練集上50次反覆運算之後的模型平均絕對誤差(mae)。我們模型的輸出是每天收盤價而非相對變化量。

對於它的精確程度我們不必太吃驚。模型能夠找到誤差的源頭並且自動調整。事實上,就算要達到零誤差也不是難事。我們可以弄幾百個神經元,反覆運算個幾千次。這個過程就是過擬合,本質上是在預測噪音。我們更應該關注的是它在測試集上的表現,因為這個對於模型是新的資料。

不算單點預測的誤導性的話,我們的LSTM模型看上去在這些沒有見過的資料上表現的也很好。最明顯的一個缺陷是它沒有預測到乙太坊價格在六月中旬和十月的突然上漲。事實上這是一個固有的問題,只是在這些尖刺上表現得更明顯。預測的價格基本上就像是真實價格向後移動了一天。更重要的是,模型似乎系統性地對乙太坊的價值高估,基本上預測線一直是在實際價格線的上方。我猜測是因為訓練集時期的資料乙太坊增長的太過驚人,所以模型認為這種趨勢會持續。我們可以對比特幣也建立一個類似的LSTM模型,測試集上的預測資料在下圖中描繪出來了。

前面我已經提到,單點預測是有欺騙性的。更近距離的看,你會發現預測資料基本上就是之前資料的鏡像。我們炫酷的深度學習LSTM模型已經部分重現了一個自回歸模型。用數學公式來表示就是:PredPrice(t)=ϕ0+ϕ1∗Price(t−1)+…+ϕp∗Price(t−p)+ϵ(t), ϵ(t)∼N(0,σ)。

好消息是自回歸模型經常被用於時序任務,說明LSTM模型的方向是靠譜的。壞消息是這是浪費LSTM的能力,我們可以花更少的時間,建一個簡單的多的自回歸模型,也能達到差不多的效果。更複雜並不意味著就更精確。

可以看出來對比單點預測這裡的結果要差一些。無論如何,我對模型體現出的一些細微的行為還是很高興的,它沒有簡單的預測價格一致的向同一個方向移動。所以還是有一些可以樂觀的地方。

回到單點預測,我們的深度神經模型看上去還行,但是簡單的隨機漫步結果也不差。跟隨機漫步模型一樣,LSTM模型也會對隨機種子的選擇敏感。所以如果我們想要比較這兩種模型,我們會在每個模型上運行多次,來估算模型的誤差。這個誤差用實際收盤價和預測的收盤價在測試集上的差來計算。

也許AI的炒作是值得的!這些圖表現了兩個模型在25個不同的初始值下的誤差。LSTM模型在比特幣和乙太坊中平均誤差分別是0.04和0.05,碾壓隨機漫步模型。

以打敗隨機漫步為目標太low了。拿LSTM和其它的時序模型來比較會更有意思。另外一方面,要改進我們的LSTM模型也不是太難,比如逐漸增加更多的層次和神經元,改變每一批資料的規模大小,學習速度等。不過,希望你能覺察到我對用深度學習預測密幣的價格的一些懷疑。因為我們忽略了最好的框架:人類智慧。顯然,預測密幣的完美『模型』是:它會永遠上漲。

總結

我們收集了一些密幣資料,然後將它們喂給了我們超酷的深度機器學習模型LSTM。不幸的是,預測的結果跟簡單地延伸之前的的價格沒有多大區別。我們如何能讓模型學習更複雜的行為呢?

1. 改變損失函數。平均絕對誤差(MAE)不鼓勵冒險。而用平均誤差方差,LSTM模型就會對尖刺和波谷更看重。

2. 對保守的自回歸類的模型懲罰。這樣會刺激深度學習演算法去探索更冒險,更有趣的模型。但是說比做容易。

3. 得到更多,更好的資料。如果單純的用過去的價格不能夠很好的預測將來的價格,我們就需要加入其他的特徵,讓這種預測能力更加強大。這樣的話,LSTM模型就不會對過去的資料如此依賴,可能能解鎖更複雜的行為。這可能是最好也是最難的解決方案。

以上是正面的解讀,負面的解讀是密幣的價格其實根本沒有模型可以預測,不管你的層次有多深。就比如看2016年的比特幣和2017年年末比特幣的瘋狂。任何建立在2016年資料上的模型都不可能預測到2017年的變化。所以建議你就用自回歸模型吧,能省不少時間呢。

但是我相信深度學習一定能夠在某寫地方有用。同時,你可以在這裡[8]下載Python代碼,訓練你自己的LSTM模型。謝謝閱讀!

[4]: https://github.com/dashee87/blogScripts/blob/master/Jupyter/2017-11-20-predicting-cryptocurrency-prices-with-deep-learning.ipynb

[8]: https://github.com/dashee87/blogScripts/blob/master/Jupyter/2017-11-20-predicting-cryptocurrency-prices-with-deep-learning.ipynb

英文原文:https://dashee87.github.io/deep%20learning/python/predicting-cryptocurrency-prices-with-deep-learning/
譯者:桂浩晉
Next Article
喜欢就按个赞吧!!!
点击关闭提示