rnn為什麼訓練速度慢?
經常看到說rnn的訓練速度比較慢,事實上我在訓練過程中也發現了這個問題,但是不清楚是什麼原因。
我看到說cnn在每一層的卷積計算中並行使用gpu的core進行了計算,所以速度比較快。那rnn為什麼會比較慢呢?
求解答,謝謝!
因為需要一個時序一個時序按順序計算
為什麼訓練RNN速度很慢?
訓練Recurrent Neural Network的速度很慢,是因為每個time step的計算,都依賴於對前一time step的計算和輸出結果。
Recurrent Neural Network訓練速度慢的問題,在處理很長的sequence的training example會更加的明顯。這個問題,也限制了deep RNN model的能夠stack的RNN的數量。VGG16可訓練weights的layer有16層。deep RNN能夠到達4層已經很少見了。
RNN訓練的速度有多慢? 用一個language model任務的例子說明。
Language Modeling Task[1]
Quasi-RNN [1] 在結構設計上不是Recurrent neural network。 它的pseudo-recurrence模似了time step的記憶,inputs layers的也很好的利用了CNN的並行性的優勢。Quasi-RNN是為NLP定製的一種CNN,可以一次讀入和處理整個sequence。
以下是Quasi-RNN訓練速度與基於LSTM的RNN的訓練速度的比較,batch size = 8
[1]
在256序列長度輸入中,Quasi-RNN是基於LSTM的RNN的12.6倍。
Forward Propagation
用一個例子說明Recurrent neural network的forward computation的dependency
"They took a vacation in Hawaii and visited the islands by bike"
在bi-gram language model中,當計算單詞「Hawaii」時,它以兩個單詞作為輸入,「vacation」,在GRU block里,計算memory cell,和計算update gate/forget gate.
當計算到「and」之後的下一個單詞時,正確的答案是什麼?
visit
visitedvisiting
正確答案是「visited」。 如果它取決於前兩個單詞「Hawaii and」,但它沒有「They took...」的context,它可能會出現語法錯誤,象是「visit」,如果是只有3個選擇的話(visit, visited, visiting)。
所以這種time step based的dependency保證了後面predict新的word的時候,有前面的context words。這個context是基於time step的hidden state,或者是output word傳遞的。
這些是具有上下文的特性,能夠在之前time steps的contextual words的情況下,在語法和語義上更準確地預測下一個單詞。但是,這種time steps dependent的sequential計算,在計算效率上有明顯的缺陷。上面的例子,在GRU block的RNN是這樣計算的
在GRU中的forward propagation將input分成一個order set的一級單詞序列
"They took a vacation in Hawaii and visited..." =&> Order set {"They", "took", ...}
- 取第一個word,計算memory cell and update/reset gates
- 取下一個word,根據先前的輸出hidden state/output, 計算hidden state, output
- 重複以上步驟10次,因為|sequence length| = 12
Recurrent neural network的forward propagation的計算複雜度為O(| Sequence Length |)。 Sequence越長,所需的計算量就越多。 並且長Sequence中的每個time step都包括一個memory I/O操作。這非常慢並且受GPU的最大線程和最大內存帶寬的約束。
[1] James Bradbury, Stephen Merity, Caiming Xiong, Richard Socher, ICLR 2017, QUASI-RECURRENT NEURAL NETWORKS
首先,說我的觀點,GPU計算RNN的過程不慢,而是RNN的特性不利於GPU加速。
慢的概念需要一個參照物,我們知道CNN裡面模型空間結構越小,前向計算越快,而RNN這個看起來空間結構很小的模型,計算時間卻不和其空間結構成比例,這裡模型空間結構就是參照物。
RNN除了有空間結構外,還有時序結構。由於,所有的時序網路都共享了同一套參數,就使得空間結構顯得特別小。
終於來了,為什麼會慢呢?有兩點,
- 計算量大。即便共享了參數,計算量卻沒有顯著減少,RNN都是用全聯接的結構。
- 計算依賴。後一幀的計算依賴前一幀的輸出。
因此,這意味RNN的每個Time Step都要在CPU和GPU來回調度一次,而CNN每一層才需要調度一次(假設GPU存儲充足)。
所以,綜上。
若有錯誤,還望指出。
- Xt代表輸入序列中的第t步元素,例如語句中的一個漢字。一般使用一個one-hot向量來表示,向量的長度是訓練所用的漢字的總數(或稱之為字典大小),而唯一為1的向量元素代表當前的漢字。
- St代表第t步的隱藏狀態,其計算公式為St=tanh(U*Xt+W*St-1)。也就是說,當前的隱藏狀態由前一個狀態和當前輸入計算得到。考慮每一步隱藏狀態的定義,可以把St視為一塊內存,它保存了之前所有步驟的輸入和隱藏狀態信息。S-1是初始狀態,被設置為全0。
- Ot是第t步的輸出。可以把它看作是對第t+1步的輸入的預測,計算公式為:Ot=softmax(V*St)。可以通過比較Ot和Xt+1之間的誤差來訓練模型。
- U,V,W是RNN的參數,並且在展開之後的每一步中依然保持不變。這就大大減少了RNN中參數的數量。
假設真實的輸出應該是
,那麼誤差可以定義為
,
是訓練樣本的index。整個網路的誤差
我們將RNN再放大一些,看看細節
令
則
矩陣向量化表示
所以梯度為:
其中
是點乘符號,即對應元素乘。
簡單點來說,RNN的訓練過程:假設一個輸入文本長度為20,然後對loss求導(W,U,V),由於是前後相互影響的,整個求導是一個疊加的過程,即可得到求導後的變化量,整個UVW是共享的。
如何有效訓練RNN是一個活躍的研究領域,有很多方法,但還沒有哪種表現出了明顯的優勢,因此也讓今天要介紹的這項工作值得注意。來自ASAPP公司和MIT的兩位研究人員提出了一種名為「簡單循環單元」(Simple Recurrent Unit,SRU)的結構,對現有門控單元做了調整,簡化了狀態計算的過程,從而展現出了與CNN、注意力和前饋網路相同的並行性。實驗結果表明,SRU訓練速度與CNN一樣,並在圖像分類、機器翻譯、問答、語音識別等各種不同任務中證明了有效性。
先看論文摘要,有個大概的了解:
標題非常直接,也是很多人都想實現的——《像訓練CNN一樣快速訓練RNN》:
摘要
RNN因其狀態計算固有的特性難以並行化因而很難擴展。例如,的前向計算要到的計算完成後才能開始,這構成了並行計算的主要瓶頸。在這項工作中,我們提出了一種RNN的替代實現,簡化了狀態計算過程,展現更多的並行性。我們所提出的循環單元,運行速度與卷積層一樣快,比cuDNN優化的LSTM快5-10倍。我們展示了這種循環單元在廣泛應用中的有效性,包括分類、問答、語言建模、翻譯和語音識別。我們開源了在PyTorch和CNTK中的實現。
簡單循環單元SRU,簡化狀態計算,速度與CNN一樣快
近來深度學習取得的許多進展都源於模型容量的增加和計算力的相應提升。模型容量增大,通常會涉及使用更大、更深的網路,而這些網路又需要複雜的超參數設置和調整。因此,不斷增大的模型和超參數數量也大大增加了訓練時間。
顯然,計算力已經成為深度學習研究的一大主要瓶頸。作為應對,研究人員開始深入挖掘並行計算的潛力,很多人使用GPU加速訓練來擴展深度學習。不過,雖然諸如卷積和注意力的運算非常適合於多線程/GPU計算,但是循環神經網路(RNN)仍然不太適合併行化。在典型的RNN實現中,輸出狀態的計算需要等到計算完成後才能開始。這阻礙了獨立計算,並大大減慢了序列處理的速度。
圖1展示了cuDNN優化後的LSTM和使用conv2d的字級卷積的處理時間。可以看出,兩者區別非常明顯,即使是優化後的LSTM,運行速度也可能慢10倍多。
圖1:cuDNN優化後的LSTM和使用conv2d的字級卷積的處理時間:即使是優化後的LSTM,運行速度也可能慢10倍多
於是,作者提出了「簡單循環單元」(Simple Recurrent Unit,SRU),並在論文中表示其計算速度明顯快於現有的循環實現。SRU簡化了狀態計算的過程,從而展現出了與CNN、注意力和前饋網路相同的並行性。
具體說,雖然SRU的內部狀態ct的更新仍然與前一個狀態ct-1有關,但是在循環步驟中不再依賴於。因此,SRU中的所有矩陣乘法(即gemm)和元素方面的操作可以在不同的維度和步驟中實現並行化。
SRU實現:增加highway連接和變分dropout
那麼,SRU是怎麼實現的呢?
作者指出,當前性能最佳的RNN,比如LSTM和GRU,都使用神經門(neural gate)控制信息流,緩解梯度消失(或爆炸)的問題。
因此,他們在此基礎上,對門控單元進行了調整。具體說,作者新增加了兩個特徵:首先,他們在循環層之間增加了highway連接,因為此前的研究已經證明,像highway連接這樣的skip connections,在訓練深度網路時非常有效;其次,在將RNN正則化時,他們在標準的dropout外,增加了變分dropout,變分dropout在時間步長t與dropout使用相同的mask。
然後,作者將和步驟t的神經門之間的連接全部丟棄,以這種方法來加速循環計算。相比之下,現有的RNN在實現時是要使用先前的輸出狀態的。
經過這樣的改善後,對於現有的深度學習庫,SRU已經可以實現超過5倍的加速。接下來,作者還進行了CUDA級的優化,並在一系列不同的基準上進行測試,評估SRU的效果。
實驗評估結果:圖像分類、語音識別、機器翻譯等任務,實現更好性能的同時,訓練速度更快
作者還在分類、問答、語言建模、翻譯和語音識別等一系列不同任務中評估了SRU。
實驗結果證實了SRU的有效性——與這些任務的循環(或卷積)基準模型相比,SRU在實現更好性能的同時,訓練速度也更快。
- 圖像分類
- 斯坦福SQuAD文本處理
- 語言建模
- 語音識別
- 機器翻譯
- 論文地址:https://arxiv.org/pdf/1709.02755.pdf
- Github地址:https://github.com/taolei87/sru
對於有使用GPU需求的朋友,可以再智星雲租用GPU,性價比很高
發佈於 2020-11-21繼續瀏覽內容知乎發現更大的世界打開Chrome繼續xingxing深度學習專業調參師,從不相信「人工智慧」
建議編寫一個只有一層一個節點的神經網路,其實就是線性擬合,看看速度。
然後你看看一個RNN裡面有多少個參數 (知名CNN網路都是M級別參數)。結合上面擬合的速度和RNN的參數就知道為什麼慢了。
建議編寫一個只有一層一個節點的神經網路,其實就是線性擬合,看看速度。
然後你看看一個RNN裡面有多少個參數 (知名CNN網路都是M級別參數)。結合上面擬合的速度和RNN的參數就知道為什麼慢了。
肯定相當慢啊。cnn是一個batch做一次前向運算和反向傳播;rnn,lstm之類是一個batch的每一個元素都要依次做一次前向和反向運算;以NLP為例,cnn是以一個句子為樣本,一次前向和反向運算就計算完這個樣本了;rnn是逐個字詞的挨個前向運算,最後挨個反向傳播之後,才算是計算完這個樣本。
因為反向傳播的路徑長....
attention+mask替代rnn,可並行計算
很大程度上 我同意崔向陽的觀點!在此 我想重述一下:
1、RNN/seq2seq的模型,此類模型中的變數是按照時間戳一步步向前(反向傳播時,為向後)進行的,如Encoder為例, ,其中 代表隱狀態, 代表輸入。這也就決定了循環網路中的計算是按照時間戳(輸入、輸出位置)來分解計算的,加之 輸入往往是可變長序列,且我們想捕獲的就是這種時序上的依賴,這種固有的序列化本質阻礙了並行化處理RNN網路的加速。
2、在CNN網路中比較方便利用批處理技術,即 batch by batch的處理數據,而且在per batch內部可以有效地利用向量化技術來加速。RNN網路中就很難做到這一點兒。當然也有一些計算分解技術,但是實現起來就不是那麼直觀。
因為序列化,不能並行
推薦閱讀: