作者 | Andrew L. Beam
編譯 | AI100
撕逼大戰,從某種角度,標誌著一個產業的火熱。
最近,大火的深度學習,也開始撕起來了。
前幾日,有一篇帖子在“Simply Stats”很火,作者Jeff Leek在博文中犀利地將深度學習拉下神壇,他談到了深度學習現在如何狂熱,人們正試圖用這個技術解決每一個問題。但是呢,只有極少數情況下,你才能拿到足夠的資料,這樣看來,深度學習也就沒那麼大用處了。
帖子原文標題為“Don’t use deep learning your data isn’t that big.”(即資料不多時,就別用深度學習了),喜歡看熱鬧的,不妨搜一下。
帖子一出,人們就炸開了。
這裡面就有牛人就看不慣了,直接懟起來!
哈佛大學生物醫藥資訊學的專業的博士後專門寫了篇文章來反駁:You can probably use deep learning even if your data isn't that big.(即便資料不夠,也能用深度學習)
誰說資料少就不能用深度學習了,那是你根本沒搞懂好嗎?
(嗯,深度學習默默表示,這鍋俺不背)
來我們先來看一下正反方的觀點:
▌正方:
原貼觀點:倘若你的樣本數量少於100個,最好不要使用深度學習,因為模型會過擬合,這樣的話,得到的結果將會很差。
▌反方:
模型表現很差並不是由過擬合引起的。沒能收斂,或者難以訓練很可能才是罪魁禍首。你正方因此得出這樣的結論,是因為你實驗本身的問題。方法用對了,即使只有100-1000個資料,仍然可以使用深度學習技術,得到好的結果。
(到底誰在扯淡?這場爭論有沒有意義?誰的實驗更有道理?歡迎各位牛人在留言區拍磚)
以下,AI100專程對反方的觀點及研究進行了全文編譯,略長,但,很有意思。準備好圍觀了嗎?出發!
以下對反方內容的全文編譯:
老實講,原文中的部分觀點,我也算是認同,不過,有一些事情需要在這篇文章中進行探討。
Jeff做了一個關於辨識手寫數字0和1的實驗,他的資料來源是來自大名鼎鼎的MNIST資料集。
此次實驗,他採用了兩種方法:
一種方法採用的是神經網路模型,共5層,其中啟用函式是雙曲正切函式;
另一種方法使用的是李加索變數選擇方法,這種方法思想就是挑選10個邊際p值最小的畫素來進行(用這些值做迴歸就可以了)。
實驗結果表明,在只有少量的樣本的情況下,李加索方法的表現要優於神經網路。
下圖是效能表現:
很驚奇對不對?
的確!倘若你的樣本數量少於100個,最好不要使用深度學習,因為模型會過擬合,這樣的話,得到的結果將會很差。
我認為在這裡需要仔細探討一下。深度學習模型很複雜,有很多的訓練技巧。我覺得模型表現很差並不是由過擬合引起的,沒能收斂,或者難以訓練很可能才是罪魁禍首。
Deep Learning VS Leekasso Redux
我們首先要做的事情就是構建一個使用MNIST資料集,並且可用的深度學習模型。一般來說我們所使用的就是多層感知機與卷積神經網路。倘若原帖思想是正確的話,那麼當我們使用少量樣本來訓練我們的模型的話,那麼我們的模型將會過擬合。
我們構建了一個簡單的多層感知機,使用的啟用函式是RELU。於此同時,我們還構建了一類似VGG的卷積神經網路。將這兩個神經網路模型的表現同李加索(Leekasso)模型進行對比。你可以在這裡獲取相關程式碼。非常感謝我的暑期實習生Michael Chen。他做了大部分的工作。使用的語言是python,工具是Keras。
程式碼獲取地址:
MLP是標準的模型,如下面程式碼所示:
我們的CNN模型的網路結構,如下面所示(我想很多人對此都很熟悉)
作為參考,我們的多層感知機MLP模型大概有120000個引數,而我們的CNN模型大概有200000個引數。根據原帖中所涉及的假設,當我們有這麼多引數,而我們的樣本數量很少的時候,我們的模型真的是要崩潰了。
我們嘗試儘可能地復原原始實驗——我們採用5折交叉驗證,但是使用標準的MNIST測試資料集做為評估使用(驗證集中0與1樣本的個數大概有2000多個)。我們將測試集分成兩部分。第一部分用來評估訓練程式的收斂性,第二部分資料用來衡量模型預測的準確度。我們並沒用對模型進行調參。對於大多數引數,我們使用的都是合理的預設值。
我們盡我們最大的努力重寫了原貼中的Leekasso和MLP程式碼的python版本。你可以在這裡獲得原始碼。下面就是每個模型在所抽取的樣本上的準確率。通過最下面的放大圖,你能夠很容易的知道哪個模型表現最好。
是不是很驚奇?這看上去和原帖的分析完全不同!原帖中所分析的MLP,在我們的試驗中,依然是在少量資料集中表現很差。但是我所設計的神經網路在所使用的樣本中,卻有很好的表現。那麼這就引出了一個問題……
到底在我們的實驗中發生了什麼?
眾所周知,深度學習模型的訓練過程是一個精細活,知道如何“照顧”我們的網路是一個很重要的技能。過多的引數會導致某些特定的問題(尤其是涉及到SGD),倘若沒有選擇好的話,那麼將會導致很差的效能,以及誤導性。當你在進行深度學習相關工作的時候,你需要謹記下面的話:
模型的細節很重要,你需要當心黑箱呼叫那些任何看起來都像是deeplearning()的東西。
下面是我對原帖中問題的一些猜想:
激勵函式很重要,使用tanh作為激勵函式的神經網路很難訓練。這就是為什麼當我們使用Relu函式作為我們的啟用函式,會有很大進步的原因了。
確保隨機梯度下降能夠收斂。在原始實驗對照中,作者僅僅訓練了20輪,這樣的話,可能是訓練的次數不夠。僅僅有10個樣本,僅僅訓練了20輪,那麼結果是我們僅僅進行了200次的梯度更新。然而要想完整的訓練一遍我們所有的資料,我們需要6000次的梯度更新。進行上百輪、上千輪訓練是很正常的。我們大概會有1000000梯度更新。假若你僅僅打算進行200次的梯度更新,那麼你可能需要很大的學習速率,否則的話,你的模型不太可能會收斂。h2o.deeplearning()預設的學習速率是0.005。假若你僅僅是更新幾次的話,這個學習速率就太小了。我們使用訓練200輪的模型,我們會看到在前50輪,模型在樣本上的準確率會有很大的波動。所以,我覺得模型沒有收斂在很大程度上能夠解釋原貼中所觀察到的差異。
需要一直檢查引數的預設值。Keras是一個很好的工具。因為Keras會將引數設定成它覺得代表當前訓練的最好的預設值。但是,你仍然需要確保你所選擇的引數的值匹配你的問題。
不同的框架會導致不同的結果。我曾嘗試回到原始的R程式碼,以期望得到最後的結果。然而,我無法從h2o.deeplearning()函式中得到好的結果。我覺得原因可能涉及到優化過程。它所使用的可能是Elastic Averaging SGD,這種方法會將計算安排到多個節點上,這樣就會加速訓練速度。我不清楚在僅有少量資料的情況下,這種方法是否會失效。我只是有這個猜測而已。對於h2o我並沒有太多的使用經驗,其他人也許知道原因。
幸運的是,Rstudio的好人們剛剛釋出了針對於Keras的R的介面。因此我可以在R的基礎上,建立我的python程式碼了。我們之前使用的MLP類似於這個樣子,現在我們用R語言將其實現。
我將這個程式碼改成了Jeff的R程式碼,並重新生成了原始的圖形。我同樣稍微修改了下Leekasso的程式碼。我發現原先的程式碼使用的是lm() (線性迴歸),我認為不是很好。所以我改成了glm()(邏輯迴歸)。新的圖形如下圖所示:
深度學習勝利了!類似的現象可能表明python與R版本的Leekasso演算法不同之處。Python版本的邏輯迴歸使用的是liblinear來實現,我覺得這樣做的話,會比R預設的實現方式更加的健壯,有更強的魯棒性。因為Leekasso選擇的變數是高度共線的,這樣做也許會更好。
這個問題意義非凡:我重新執行了Leekasso,但是僅使用最高的預測值,最終的結果和完整的Leekasso的結果一致。事實上,我認為我可以做出一個不需要資料的分類器,這個分類器會有很高的準確率。我們僅僅需要選擇中心的畫素,假若它是黑色的話,我們就可以認為它是1,否則的話就預測是0。正如David Robinson所指出的:
David同樣認為對於大部分的數字對兒,我們只需使用一個畫素就能分開。因此,那個帖子反映的問題看上去並不能反應資料很少的情形。我們對他得出結論最好有所保留。
為什麼深度學習會產生誤解?
最後,我想在重新回顧一下Jeff在他原帖中的觀點,尤其是下面的陳述:
問題是,現在僅僅有很少的領域可獲得資料,並使用深度學習技術進行處理……但是,我認為深度學習對於簡單模型的優勢在於深度學習可處理大量的資料以及大量的引數。
我並不是贊同這一段,尤其是最後一部分的觀點。許多人認為深度學習是一個巨大的黑箱。這個黑箱有海量的引數,只要你能夠提供足夠多的資料(這裡足夠多所代表的資料量在一百萬和葛立恆數之間),你就能學習到任何的函式。很明顯,神經網路極其的靈活,它的靈活性是神經網路之所以取得成功的部分原因。但是,這並不是唯一的原因,對不對?
畢竟,統計學與機器學習對超級靈活模型的研究已經有70多年了。我並不認為神經網路相較於其他擁有同樣複雜度的演算法,會擁有更好的靈活性。
以下是我認為為什麼神經網路會取得成功的一些原因:
1.任何措施都是為了取得偏差與方差的平衡:
需要說清楚的是,我認為Jeff實際上想要討論的模型複雜度與偏差/方差的平衡。假若你沒有足夠多的資料,那麼使用簡單的模型相比於複雜模型來說可能會更好(簡單模型意味著高偏差/低方差,複雜模型意味著低偏差/高方差)。我認為在大部分情況下,這是一個很好的客觀建議。然而……
2.神經網路有很多的方法來避免過擬合:
神經網路有很多的引數。在Jeff看來,倘若我們沒有足夠多的資料來估計這些引數的話,這就會導致高方差。人們很清楚這個問題,並研究出了很多可降低方差的技術。像dropout與隨機梯度下結合,就會起到bagging演算法的作用。我們只不過使用網路引數來代替輸入變數。降低方差的技術,比如說dropout,專屬於訓練過程,在某種程度上來說,其他模型很難使用。這樣的話,即使你沒有海量的資料,你依然可以訓練巨大的模型(就像是我們的MLP,擁有120000個引數)。
3.深度學習能夠輕易地將具體問題的限制條件輸入到我們的模型當中,這樣很容易降低偏差:
這是我認為最重要的部分。然而,我們卻經常將這一點忽略掉。神經網路具有模組化功能,它可以包含強大的約束條件(或者說是先驗),這樣就能夠在很大程度上降低模型的方差。最好的例子就是卷積神經網路。在一個CNN中,我們將影象的特徵經過編碼,然後輸入到模型當中去。例如,我們使用一個3X3的卷積,我們這樣做實際上就是在告訴我們的網路區域性關聯的小的畫素集合會包含有用的資訊。此外,我們可以將經過平移與旋轉的但是不變的影象,通過編碼來輸入到我們的模型當中。這都有助於我們降低模型對圖片特徵的偏差。並能夠大幅度降低方差並提高模型的預測能力。
4.使用深度學習並不需要如google一般的海量資料:
使用上面所提及的方法,即使你是普通人,僅僅擁有100-1000個資料,你仍然可以使用深度學習技術,並從中受益。通過使用這些技術,你不僅可以降低方差,同時也不會降低神經網路的靈活性。你甚至可以通過遷移學習的方法,來在其他任務上來構建網路。
總之,我認為上面的所列舉的理由已經能夠很好地解釋為什麼深度學習在實際中會有效。它之所以有效,並不僅僅是因為它擁有大量的引數以及海量的資料。最後,我想說的是本文並沒有說Jeff的觀點是錯誤的,本文僅僅是從不同的角度來解讀他的觀點。希望這篇文章對你有用。
原文地址
https://simplystatistics.org/2017/05/31/deeplearning-vs-leekasso/
PS:關於正方的觀點,請檢視:
http://beamandrew.github.io/deeplearning/2017/06/04/deep_learning_works.html