深度学习笔记第二门课 改善深层神经网络 第一周:深度学习的实践层面
本文是吳恩達老師的深度學習課程[1]筆記部分。
作者:黃海廣[2]
主要編寫人員:黃海廣、林興木(第四所有底稿,第五課第一二周,第三周前三節)、祝彥森:(第三課所有底稿)、賀志堯(第五課第三周底稿)、王翔、胡瀚文、 余笑、 鄭浩、李懷松、 朱越鵬、陳偉賀、 曹越、 路皓翔、邱牧宸、 唐天澤、 張浩、 陳志豪、 游忍、 澤霖、沈偉臣、 賈紅順、 時超、 陳哲、趙一帆、 胡瀟楊、段希、于沖、張鑫倩
參與編輯人員:黃海廣、陳康凱、石晴路、鐘博彥、向偉、嚴鳳龍、劉成 、賀志堯、段希、陳瑤、林家泳、王翔、 謝士晨、蔣鵬
備注:筆記和作業(含數據、原始作業文件)、視頻都在?github[3]中下載。
我將陸續將課程筆記發布在公眾號“機器學習初學者”,敬請關注。
第二門課 改善深層神經網絡:超參數調試、正則化以及優化(Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)
第一周:深度學習的實踐層面(Practical aspects of Deep Learning)
1.1 訓練,驗證,測試集(Train / Dev / Test sets)
大家可能已經了解了,那么本周,我們將繼續學習如何有效運作神經網絡,內容涉及超參數調優,如何構建數據,以及如何確保優化算法快速運行,從而使學習算法在合理時間內完成自我學習。
第一周,我們首先說說神經網絡機器學習中的問題,然后是隨機神經網絡,還會學習一些確保神經網絡正確運行的技巧,帶著這些問題,我們開始今天的課程。
在配置訓練、驗證和測試數據集的過程中做出正確決策會在很大程度上幫助大家創建高效的神經網絡。訓練神經網絡時,我們需要做出很多決策,例如:
神經網絡分多少層
每層含有多少個隱藏單元
學習速率是多少
各層采用哪些激活函數
創建新應用的過程中,我們不可能從一開始就準確預測出這些信息和其他超級參數。實際上,應用型機器學習是一個高度迭代的過程,通常在項目啟動時,我們會先有一個初步想法,比如構建一個含有特定層數,隱藏單元數量或數據集個數等等的神經網絡,然后編碼,并嘗試運行這些代碼,通過運行和測試得到該神經網絡或這些配置信息的運行結果,你可能會根據輸出結果重新完善自己的想法,改變策略,或者為了找到更好的神經網絡不斷迭代更新自己的方案。
現如今,深度學習已經在自然語言處理,計算機視覺,語音識別以及結構化數據應用等眾多領域取得巨大成功。結構化數據無所不包,從廣告到網絡搜索。其中網絡搜索不僅包括網絡搜索引擎,還包括購物網站,從所有根據搜索欄詞條傳輸結果的網站。再到計算機安全,物流,比如判斷司機去哪接送貨,范圍之廣,不勝枚舉。
我發現,可能有自然語言處理方面的人才想踏足計算機視覺領域,或者經驗豐富的語音識別專家想投身廣告行業,又或者,有的人想從電腦安全領域跳到物流行業,在我看來,從一個領域或者應用領域得來的直覺經驗,通常無法轉移到其他應用領域,最佳決策取決于你所擁有的數據量,計算機配置中輸入特征的數量,用GPU訓練還是CPU,GPU和CPU的具體配置以及其他諸多因素。
目前為止,我覺得,對于很多應用系統,即使是經驗豐富的深度學習行家也不太可能一開始就預設出最匹配的超級參數,所以說,應用深度學習是一個典型的迭代過程,需要多次循環往復,才能為應用程序找到一個稱心的神經網絡,因此循環該過程的效率是決定項目進展速度的一個關鍵因素,而創建高質量的訓練數據集,驗證集和測試集也有助于提高循環效率。
假設這是訓練數據,我用一個長方形表示,我們通常會將這些數據劃分成幾部分,一部分作為訓練集,一部分作為簡單交叉驗證集,有時也稱之為驗證集,方便起見,我就叫它驗證集(dev set),其實都是同一個概念,最后一部分則作為測試集。
接下來,我們開始對訓練集執行算法,通過驗證集或簡單交叉驗證集選擇最好的模型,經過充分驗證,我們選定了最終模型,然后就可以在測試集上進行評估了,為了無偏評估算法的運行狀況。
在機器學習發展的小數據量時代,常見做法是將所有數據三七分,就是人們常說的70%訓練集,30%測試集。如果明確設置了驗證集,也可以按照60%訓練集,20%驗證集和20%測試集來劃分。這是前幾年機器學習領域普遍認可的最好的實踐方法。
如果只有100條,1000條或者1萬條數據,那么上述比例劃分是非常合理的。
但是在大數據時代,我們現在的數據量可能是百萬級別,那么驗證集和測試集占數據總量的比例會趨向于變得更小。因為驗證集的目的就是驗證不同的算法,檢驗哪種算法更有效,因此,驗證集只要足夠大到能評估不同的算法,比如2個甚至10個不同算法,并迅速判斷出哪種算法更有效。我們可能不需要拿出20%的數據作為驗證集。
比如我們有100萬條數據,那么取1萬條數據便足以進行評估,找出其中表現最好的1-2種算法。同樣地,根據最終選擇的分類器,測試集的主要目的是正確評估分類器的性能,所以,如果擁有百萬數據,我們只需要1000條數據,便足以評估單個分類器,并且準確評估該分類器的性能。假設我們有100萬條數據,其中1萬條作為驗證集,1萬條作為測試集,100萬里取1萬,比例是1%,即:訓練集占98%,驗證集和測試集各占1%。對于數據量過百萬的應用,訓練集可以占到99.5%,驗證和測試集各占0.25%,或者驗證集占0.4%,測試集占0.1%。
總結一下,在機器學習中,我們通常將樣本分成訓練集,驗證集和測試集三部分,數據集規模相對較小,適用傳統的劃分比例,數據集規模較大的,驗證集和測試集要小于數據總量的20%或10%。后面我會給出如何劃分驗證集和測試集的具體指導。
現代深度學習的另一個趨勢是越來越多的人在訓練和測試集分布不匹配的情況下進行訓練,假設你要構建一個用戶可以上傳大量圖片的應用程序,目的是找出并呈現所有貓咪圖片,可能你的用戶都是愛貓人士,訓練集可能是從網上下載的貓咪圖片,而驗證集和測試集是用戶在這個應用上上傳的貓的圖片,就是說,訓練集可能是從網絡上抓下來的圖片。而驗證集和測試集是用戶上傳的圖片。結果許多網頁上的貓咪圖片分辨率很高,很專業,后期制作精良,而用戶上傳的照片可能是用手機隨意拍攝的,像素低,比較模糊,這兩類數據有所不同,針對這種情況,根據經驗,我建議大家要確保驗證集和測試集的數據來自同一分布,關于這個問題我也會多講一些。因為你們要用驗證集來評估不同的模型,盡可能地優化性能。如果驗證集和測試集來自同一個分布就會很好。
但由于深度學習算法需要大量的訓練數據,為了獲取更大規模的訓練數據集,我們可以采用當前流行的各種創意策略,例如,網頁抓取,代價就是訓練集數據與驗證集和測試集數據有可能不是來自同一分布。但只要遵循這個經驗法則,你就會發現機器學習算法會變得更快。我會在后面的課程中更加詳細地解釋這條經驗法則。
最后一點,就算沒有測試集也不要緊,測試集的目的是對最終所選定的神經網絡系統做出無偏估計,如果不需要無偏估計,也可以不設置測試集。所以如果只有驗證集,沒有測試集,我們要做的就是,在訓練集上訓練,嘗試不同的模型框架,在驗證集上評估這些模型,然后迭代并選出適用的模型。因為驗證集中已經涵蓋測試集數據,其不再提供無偏性能評估。當然,如果你不需要無偏估計,那就再好不過了。
在機器學習中,如果只有一個訓練集和一個驗證集,而沒有獨立的測試集,遇到這種情況,訓練集還被人們稱為訓練集,而驗證集則被稱為測試集,不過在實際應用中,人們只是把測試集當成簡單交叉驗證集使用,并沒有完全實現該術語的功能,因為他們把驗證集數據過度擬合到了測試集中。如果某團隊跟你說他們只設置了一個訓練集和一個測試集,我會很謹慎,心想他們是不是真的有訓練驗證集,因為他們把驗證集數據過度擬合到了測試集中,讓這些團隊改變叫法,改稱其為“訓練驗證集”,而不是“訓練測試集”,可能不太容易。即便我認為“訓練驗證集“在專業用詞上更準確。實際上,如果你不需要無偏評估算法性能,那么這樣是可以的。
所以說,搭建訓練驗證集和測試集能夠加速神經網絡的集成,也可以更有效地衡量算法地偏差和方差,從而幫助我們更高效地選擇合適方法來優化算法。
1.2 偏差,方差(Bias /Variance)
我注意到,幾乎所有機器學習從業人員都期望深刻理解偏差和方差,這兩個概念易學難精,即使你自己認為已經理解了偏差和方差的基本概念,卻總有一些意想不到的新東西出現。關于深度學習的誤差問題,另一個趨勢是對偏差和方差的權衡研究甚淺,你可能聽說過這兩個概念,但深度學習的誤差很少權衡二者,我們總是分別考慮偏差和方差,卻很少談及偏差和方差的權衡問題,下面我們來一探究竟。
假設這就是數據集,如果給這個數據集擬合一條直線,可能得到一個邏輯回歸擬合,但它并不能很好地擬合該數據,這是高偏差(high bias)的情況,我們稱為“欠擬合”(underfitting)。
相反的如果我們擬合一個非常復雜的分類器,比如深度神經網絡或含有隱藏單元的神經網絡,可能就非常適用于這個數據集,但是這看起來也不是一種很好的擬合方式分類器方差較高(high variance),數據過度擬合(overfitting)。
在兩者之間,可能還有一些像圖中這樣的,復雜程度適中,數據擬合適度的分類器,這個數據擬合看起來更加合理,我們稱之為“適度擬合”(just right)是介于過度擬合和欠擬合中間的一類。
在這樣一個只有和兩個特征的二維數據集中,我們可以繪制數據,將偏差和方差可視化。在多維空間數據中,繪制數據和可視化分割邊界無法實現,但我們可以通過幾個指標,來研究偏差和方差。
我們沿用貓咪圖片分類這個例子,左邊一張是貓咪圖片,右邊一張不是。理解偏差和方差的兩個關鍵數據是訓練集誤差(Train set error)和驗證集誤差(Dev set error),為了方便論證,假設我們可以辨別圖片中的小貓,我們用肉眼識別幾乎是不會出錯的。
假定訓練集誤差是1%,為了方便論證,假定驗證集誤差是11%,可以看出訓練集設置得非常好,而驗證集設置相對較差,我們可能過度擬合了訓練集,在某種程度上,驗證集并沒有充分利用交叉驗證集的作用,像這種情況,我們稱之為“高方差”。
通過查看訓練集誤差和驗證集誤差,我們便可以診斷算法是否具有高方差。也就是說衡量訓練集和驗證集誤差就可以得出不同結論。
假設訓練集誤差是15%,我們把訓練集誤差寫在首行,驗證集誤差是16%,假設該案例中人的錯誤率幾乎為0%,人們瀏覽這些圖片,分辨出是不是貓。算法并沒有在訓練集中得到很好訓練,如果訓練數據的擬合度不高,就是數據欠擬合,就可以說這種算法偏差比較高。相反,它對于驗證集產生的結果卻是合理的,驗證集中的錯誤率只比訓練集的多了1%,所以這種算法偏差高,因為它甚至不能擬合訓練集,這與上一張幻燈片最左邊的圖片相似。
再舉一個例子,訓練集誤差是15%,偏差相當高,但是,驗證集的評估結果更糟糕,錯誤率達到30%,在這種情況下,我會認為這種算法偏差高,因為它在訓練集上結果不理想,而且方差也很高,這是方差偏差都很糟糕的情況。
再看最后一個例子,訓練集誤差是0.5%,驗證集誤差是1%,用戶看到這樣的結果會很開心,貓咪分類器只有1%的錯誤率,偏差和方差都很低。
有一點我先在這個簡單提一下,具體的留在后面課程里講,這些分析都是基于假設預測的,假設人眼辨別的錯誤率接近0%,一般來說,最優誤差也被稱為貝葉斯誤差,所以,最優誤差接近0%,我就不在這里細講了,如果最優誤差或貝葉斯誤差非常高,比如15%。我們再看看這個分類器(訓練誤差15%,驗證誤差16%),15%的錯誤率對訓練集來說也是非常合理的,偏差不高,方差也非常低。
當所有分類器都不適用時,如何分析偏差和方差呢?比如,圖片很模糊,即使是人眼,或者沒有系統可以準確無誤地識別圖片,在這種情況下,最優誤差會更高,那么分析過程就要做些改變了,我們暫時先不討論這些細微差別,重點是通過查看訓練集誤差,我們可以判斷數據擬合情況,至少對于訓練數據是這樣,可以判斷是否有偏差問題,然后查看錯誤率有多高。當完成訓練集訓練,開始使用驗證集驗證時,我們可以判斷方差是否過高,從訓練集到驗證集的這個過程中,我們可以判斷方差是否過高。
以上分析的前提都是假設基本誤差很小,訓練集和驗證集數據來自相同分布,如果沒有這些假設作為前提,分析過程更加復雜,我們將會在稍后課程里討論。
上一張幻燈片,我們講了高偏差和高方差的情況,大家應該對優質分類器有了一定的認識,偏差和方差都高是什么樣子呢?這種情況對于兩個衡量標準來說都是非常糟糕的。
我們之前講過,這樣的分類器,會產生高偏差,因為它的數據擬合度低,像這種接近線性的分類器,數據擬合度低。
但是如果我們稍微改變一下分類器,我用紫色筆畫出,它會過度擬合部分數據,用紫色線畫出的分類器具有高偏差和高方差,偏差高是因為它幾乎是一條線性分類器,并未擬合數據。
這種二次曲線能夠很好地擬合數據。
這條曲線中間部分靈活性非常高,卻過度擬合了這兩個樣本,這類分類器偏差很高,因為它幾乎是線性的。
而采用曲線函數或二次元函數會產生高方差,因為它曲線靈活性太高以致擬合了這兩個錯誤樣本和中間這些活躍數據。
這看起來有些不自然,從兩個維度上看都不太自然,但對于高維數據,有些數據區域偏差高,有些數據區域方差高,所以在高維數據中采用這種分類器看起來就不會那么牽強了。
總結一下,我們講了如何通過分析在訓練集上訓練算法產生的誤差和驗證集上驗證算法產生的誤差來診斷算法是否存在高偏差和高方差,是否兩個值都高,或者兩個值都不高,根據算法偏差和方差的具體情況決定接下來你要做的工作,下節課,我會根據算法偏差和方差的高低情況講解一些機器學習的基本方法,幫助大家更系統地優化算法,我們下節課見。
1.3 機器學習基礎(Basic Recipe for Machine Learning)
上節課我們講的是如何通過訓練誤差和驗證集誤差判斷算法偏差或方差是否偏高,幫助我們更加系統地在機器學習中運用這些方法來優化算法性能。
下圖就是我在訓練神經網絡用到的基本方法:(嘗試這些方法,可能有用,可能沒用)
這是我在訓練神經網絡時用到的基本方法,初始模型訓練完成后,我首先要知道算法的偏差高不高,如果偏差較高,試著評估訓練集或訓練數據的性能。如果偏差的確很高,甚至無法擬合訓練集,那么你要做的就是選擇一個新的網絡,比如含有更多隱藏層或者隱藏單元的網絡,或者花費更多時間來訓練網絡,或者嘗試更先進的優化算法,后面我們會講到這部分內容。你也可以嘗試其他方法,可能有用,也可能沒用。
一會兒我們會看到許多不同的神經網絡架構,或許你能找到一個更合適解決此問題的新的網絡架構,加上括號,因為其中一條就是你必須去嘗試,可能有用,也可能沒用,不過采用規模更大的網絡通常都會有所幫助,延長訓練時間不一定有用,但也沒什么壞處。訓練學習算法時,我會不斷嘗試這些方法,直到解決掉偏差問題,這是最低標準,反復嘗試,直到可以擬合數據為止,至少能夠擬合訓練集。
如果網絡足夠大,通常可以很好的擬合訓練集,只要你能擴大網絡規模,如果圖片很模糊,算法可能無法擬合該圖片,但如果有人可以分辨出圖片,如果你覺得基本誤差不是很高,那么訓練一個更大的網絡,你就應該可以……至少可以很好地擬合訓練集,至少可以擬合或者過擬合訓練集。一旦偏差降低到可以接受的數值,檢查一下方差有沒有問題,為了評估方差,我們要查看驗證集性能,我們能從一個性能理想的訓練集推斷出驗證集的性能是否也理想,如果方差高,最好的解決辦法就是采用更多數據,如果你能做到,會有一定的幫助,但有時候,我們無法獲得更多數據,我們也可以嘗試通過正則化來減少過擬合,這個我們下節課會講。有時候我們不得不反復嘗試,但是,如果能找到更合適的神經網絡框架,有時它可能會一箭雙雕,同時減少方差和偏差。如何實現呢?想系統地說出做法很難,總之就是不斷重復嘗試,直到找到一個低偏差,低方差的框架,這時你就成功了。
有兩點需要大家注意:
第一點,高偏差和高方差是兩種不同的情況,我們后續要嘗試的方法也可能完全不同,我通常會用訓練驗證集來診斷算法是否存在偏差或方差問題,然后根據結果選擇嘗試部分方法。舉個例子,如果算法存在高偏差問題,準備更多訓練數據其實也沒什么用處,至少這不是更有效的方法,所以大家要清楚存在的問題是偏差還是方差,還是兩者都有問題,明確這一點有助于我們選擇出最有效的方法。
第二點,在機器學習的初期階段,關于所謂的偏差方差權衡的討論屢見不鮮,原因是我們能嘗試的方法有很多。可以增加偏差,減少方差,也可以減少偏差,增加方差,但是在深度學習的早期階段,我們沒有太多工具可以做到只減少偏差或方差卻不影響到另一方。但在當前的深度學習和大數據時代,只要持續訓練一個更大的網絡,只要準備了更多數據,那么也并非只有這兩種情況,我們假定是這樣,那么,只要正則適度,通常構建一個更大的網絡便可以,在不影響方差的同時減少偏差,而采用更多數據通常可以在不過多影響偏差的同時減少方差。這兩步實際要做的工作是:訓練網絡,選擇網絡或者準備更多數據,現在我們有工具可以做到在減少偏差或方差的同時,不對另一方產生過多不良影響。我覺得這就是深度學習對監督式學習大有裨益的一個重要原因,也是我們不用太過關注如何平衡偏差和方差的一個重要原因,但有時我們有很多選擇,減少偏差或方差而不增加另一方。最終,我們會得到一個非常規范化的網絡。從下節課開始,我們將講解正則化,訓練一個更大的網絡幾乎沒有任何負面影響,而訓練一個大型神經網絡的主要代價也只是計算時間,前提是網絡是比較規范化的。
今天我們講了如何通過組織機器學習來診斷偏差和方差的基本方法,然后選擇解決問題的正確操作,希望大家有所了解和認識。我在課上不止一次提到了正則化,它是一種非常實用的減少方差的方法,正則化時會出現偏差方差權衡問題,偏差可能略有增加,如果網絡足夠大,增幅通常不會太高,我們下節課再細講,以便大家更好理解如何實現神經網絡的正則化。
1.4 正則化(Regularization)
深度學習可能存在過擬合問題——高方差,有兩個解決方法,一個是正則化,另一個是準備更多的數據,這是非常可靠的方法,但你可能無法時時刻刻準備足夠多的訓練數據或者獲取更多數據的成本很高,但正則化通常有助于避免過擬合或減少你的網絡誤差。
如果你懷疑神經網絡過度擬合了數據,即存在高方差問題,那么最先想到的方法可能是正則化,另一個解決高方差的方法就是準備更多數據,這也是非常可靠的辦法,但你可能無法時時準備足夠多的訓練數據,或者,獲取更多數據的成本很高,但正則化有助于避免過度擬合,或者減少網絡誤差,下面我們就來講講正則化的作用原理。
我們用邏輯回歸來實現這些設想,求成本函數的最小值,它是我們定義的成本函數,參數包含一些訓練數據和不同數據中個體預測的損失,和是邏輯回歸的兩個參數,是一個多維度參數矢量,是一個實數。在邏輯回歸函數中加入正則化,只需添加參數λ,也就是正則化參數,一會兒再詳細講。
乘以范數的平方,其中是的歐幾里德范數的平方,等于(?值從1到)平方的和,也可表示為,也就是向量參數?的歐幾里德范數(2范數)的平方,此方法稱為正則化,因為這里用了歐幾里德范數,被稱為向量參數的范數。
為什么只正則化參數?為什么不再加上參數??呢?你可以這么做,只是我習慣省略不寫,因為通常是一個高維參數矢量,已經可以表達高偏差問題,可能包含有很多參數,我們不可能擬合所有參數,而只是單個數字,所以幾乎涵蓋所有參數,而不是,如果加了參數,其實也沒太大影響,因為只是眾多參數中的一個,所以我通常省略不計,如果你想加上這個參數,完全沒問題。
正則化是最常見的正則化類型,你們可能聽說過正則化,正則化,加的不是范數,而是正則項乘以,也被稱為參數向量的范數,無論分母是還是,它都是一個比例常量。
如果用的是正則化,最終會是稀疏的,也就是說向量中有很多0,有人說這樣有利于壓縮模型,因為集合中參數均為0,存儲模型所占用的內存更少。實際上,雖然正則化使模型變得稀疏,卻沒有降低太多存儲內存,所以我認為這并不是正則化的目的,至少不是為了壓縮模型,人們在訓練網絡時,越來越傾向于使用正則化。
我們來看最后一個細節,是正則化參數,我們通常使用驗證集或交叉驗證集來配置這個參數,嘗試各種各樣的數據,尋找最好的參數,我們要考慮訓練集之間的權衡,把參數設置為較小值,這樣可以避免過擬合,所以λ是另外一個需要調整的超級參數,順便說一下,為了方便寫代碼,在Python編程語言中,是一個保留字段,編寫代碼時,我們刪掉,寫成,以免與Python中的保留字段沖突,這就是在邏輯回歸函數中實現正則化的過程,如何在神經網絡中實現正則化呢?
神經網絡含有一個成本函數,該函數包含,到,所有參數,字母是神經網絡所含的層數,因此成本函數等于個訓練樣本損失函數的總和乘以,正則項為,我們稱為范數平方,這個矩陣范數(即平方范數),被定義為矩陣中所有元素的平方求和,
我們看下求和公式的具體參數,第一個求和符號其值從1到,第二個其值從1到,因為是一個的多維矩陣,表示?層單元的數量,表示第層隱藏單元的數量。
該矩陣范數被稱作“弗羅貝尼烏斯范數”,用下標標注”,鑒于線性代數中一些神秘晦澀的原因,我們不稱之為“矩陣范數”,而稱它為“弗羅貝尼烏斯范數”,矩陣范數聽起來更自然,但鑒于一些大家無須知道的特殊原因,按照慣例,我們稱之為“弗羅貝尼烏斯范數”,它表示一個矩陣中所有元素的平方和。
該如何使用該范數實現梯度下降呢?
用backprop計算出的值,backprop會給出對的偏導數,實際上是,把替換為減去學習率乘以。
這就是之前我們額外增加的正則化項,既然已經增加了這個正則項,現在我們要做的就是給加上這一項,然后計算這個更新項,使用新定義的,它的定義含有相關參數代價函數導數和,以及最后添加的額外正則項,這也是正則化有時被稱為“權重衰減”的原因。
我們用的定義替換此處的,可以看到,的定義被更新為減去學習率?乘以backprop 再加上。
該正則項說明,不論是什么,我們都試圖讓它變得更小,實際上,相當于我們給矩陣W乘以倍的權重,矩陣減去倍的它,也就是用這個系數乘以矩陣,該系數小于1,因此范數正則化也被稱為“權重衰減”,因為它就像一般的梯度下降,被更新為少了乘以backprop輸出的最初梯度值,同時也乘以了這個系數,這個系數小于1,因此正則化也被稱為“權重衰減”。
我不打算這么叫它,之所以叫它“權重衰減”是因為這兩項相等,權重指標乘以了一個小于1的系數。
以上就是在神經網絡中應用正則化的過程,有人會問我,為什么正則化可以預防過擬合,我們放在下節課講,同時直觀感受一下正則化是如何預防過擬合的。
1.5 為什么正則化有利于預防過擬合呢?(Why regularization reduces overfitting?)
為什么正則化有利于預防過擬合呢?為什么它可以減少方差問題?我們通過兩個例子來直觀體會一下。
左圖是高偏差,右圖是高方差,中間是Just Right,這幾張圖我們在前面課程中看到過。
現在我們來看下這個龐大的深度擬合神經網絡。我知道這張圖不夠大,深度也不夠,但你可以想象這是一個過擬合的神經網絡。這是我們的代價函數,含有參數,。我們添加正則項,它可以避免數據權值矩陣過大,這就是弗羅貝尼烏斯范數,為什么壓縮范數,或者弗羅貝尼烏斯范數或者參數可以減少過擬合?
直觀上理解就是如果正則化設置得足夠大,權重矩陣被設置為接近于0的值,直觀理解就是把多隱藏單元的權重設為0,于是基本上消除了這些隱藏單元的許多影響。如果是這種情況,這個被大大簡化了的神經網絡會變成一個很小的網絡,小到如同一個邏輯回歸單元,可是深度卻很大,它會使這個網絡從過度擬合的狀態更接近左圖的高偏差狀態。
但是會存在一個中間值,于是會有一個接近“Just Right”的中間狀態。
直觀理解就是增加到足夠大,會接近于0,實際上是不會發生這種情況的,我們嘗試消除或至少減少許多隱藏單元的影響,最終這個網絡會變得更簡單,這個神經網絡越來越接近邏輯回歸,我們直覺上認為大量隱藏單元被完全消除了,其實不然,實際上是該神經網絡的所有隱藏單元依然存在,但是它們的影響變得更小了。神經網絡變得更簡單了,貌似這樣更不容易發生過擬合,因此我不確定這個直覺經驗是否有用,不過在編程中執行正則化時,你實際看到一些方差減少的結果。
我們再來直觀感受一下,正則化為什么可以預防過擬合,假設我們用的是這樣的雙曲線激活函數。
用表示,我們發現如果 z 非常小,比如 z 只涉及很小范圍的參數(圖中原點附近的紅色區域),這里我們利用了雙曲正切函數的線性狀態,只要可以擴展為這樣的更大值或者更小值,激活函數開始變得非線性。
現在你應該摒棄這個直覺,如果正則化參數λ很大,激活函數的參數會相對較小,因為代價函數中的參數變大了,如果很小,
如果很小,相對來說,也會很小。
特別是,如果的值最終在這個范圍內,都是相對較小的值,大致呈線性,每層幾乎都是線性的,和線性回歸函數一樣。
第一節課我們講過,如果每層都是線性的,那么整個網絡就是一個線性網絡,即使是一個非常深的深層網絡,因具有線性激活函數的特征,最終我們只能計算線性函數,因此,它不適用于非常復雜的決策,以及過度擬合數據集的非線性決策邊界,如同我們在幻燈片中看到的過度擬合高方差的情況。
總結一下,如果正則化參數變得很大,參數很小,也會相對變小,此時忽略的影響,會相對變小,實際上,的取值范圍很小,這個激活函數,也就是曲線函數會相對呈線性,整個神經網絡會計算離線性函數近的值,這個線性函數非常簡單,并不是一個極復雜的高度非線性函數,不會發生過擬合。
大家在編程作業里實現正則化的時候,會親眼看到這些結果,總結正則化之前,我給大家一個執行方面的小建議,在增加正則化項時,應用之前定義的代價函數,我們做過修改,增加了一項,目的是預防權重過大。
如果你使用的是梯度下降函數,在調試梯度下降時,其中一步就是把代價函數設計成這樣一個函數,在調試梯度下降時,它代表梯度下降的調幅數量。可以看到,代價函數對于梯度下降的每個調幅都單調遞減。如果你實施的是正則化函數,請牢記,已經有一個全新的定義。如果你用的是原函數,也就是這第一個項正則化項,你可能看不到單調遞減現象,為了調試梯度下降,請務必使用新定義的函數,它包含第二個正則化項,否則函數可能不會在所有調幅范圍內都單調遞減。
這就是正則化,它是我在訓練深度學習模型時最常用的一種方法。在深度學習中,還有一種方法也用到了正則化,就是dropout正則化,我們下節課再講。
1.6 dropout 正則化(Dropout Regularization)
除了正則化,還有一個非常實用的正則化方法——“Dropout(隨機失活)”,我們來看看它的工作原理。
假設你在訓練上圖這樣的神經網絡,它存在過擬合,這就是dropout所要處理的,我們復制這個神經網絡,dropout會遍歷網絡的每一層,并設置消除神經網絡中節點的概率。假設網絡中的每一層,每個節點都以拋硬幣的方式設置概率,每個節點得以保留和消除的概率都是0.5,設置完節點概率,我們會消除一些節點,然后刪除掉從該節點進出的連線,最后得到一個節點更少,規模更小的網絡,然后用backprop方法進行訓練。
這是網絡節點精簡后的一個樣本,對于其它樣本,我們照舊以拋硬幣的方式設置概率,保留一類節點集合,刪除其它類型的節點集合。對于每個訓練樣本,我們都將采用一個精簡后神經網絡來訓練它,這種方法似乎有點怪,單純遍歷節點,編碼也是隨機的,可它真的有效。不過可想而知,我們針對每個訓練樣本訓練規模小得多的網絡,最后你可能會認識到為什么要正則化網絡,因為我們在訓練規模小得多的網絡。
如何實施dropout呢?方法有幾種,接下來我要講的是最常用的方法,即inverted dropout(反向隨機失活),出于完整性考慮,我們用一個三層()網絡來舉例說明。編碼中會有很多涉及到3的地方。我只舉例說明如何在某一層中實施dropout。
首先要定義向量,表示網絡第三層的dropout向量:
d3 = np.random.rand(a3.shape[0],a3.shape[1])
然后看它是否小于某數,我們稱之為keep-prob,keep-prob是一個具體數字,上個示例中它是0.5,而本例中它是0.8,它表示保留某個隱藏單元的概率,此處keep-prob等于0.8,它意味著消除任意一個隱藏單元的概率是0.2,它的作用就是生成隨機矩陣,如果對進行因子分解,效果也是一樣的。是一個矩陣,每個樣本和每個隱藏單元,其中中的對應值為1的概率都是0.8,對應為0的概率是0.2,隨機數字小于0.8。它等于1的概率是0.8,等于0的概率是0.2。
接下來要做的就是從第三層中獲取激活函數,這里我們叫它,含有要計算的激活函數,等于上面的乘以,a3 =np.multiply(a3,d3),這里是元素相乘,也可寫為,它的作用就是讓中所有等于0的元素(輸出),而各個元素等于0的概率只有20%,乘法運算最終把中相應元素輸出,即讓中0元素與中相對元素歸零。
如果用python實現該算法的話,則是一個布爾型數組,值為true和false,而不是1和0,乘法運算依然有效,python會把true和false翻譯為1和0,大家可以用python嘗試一下。
最后,我們向外擴展,用它除以0.8,或者除以keep-prob參數。
下面我解釋一下為什么要這么做,為方便起見,我們假設第三隱藏層上有50個單元或50個神經元,在一維上是50,我們通過因子分解將它拆分成維的,保留和刪除它們的概率分別為80%和20%,這意味著最后被刪除或歸零的單元平均有10(50×20%=10)個,現在我們看下,,我們的預期是,減少20%,也就是說中有20%的元素被歸零,為了不影響的期望值,我們需要用,它將會修正或彌補我們所需的那20%,的期望值不會變,劃線部分就是所謂的dropout方法。
它的功能是,不論keep-prop的值是多少0.8,0.9甚至是1,如果keep-prop設置為1,那么就不存在dropout,因為它會保留所有節點。反向隨機失活(inverted dropout)方法通過除以keep-prob,確保的期望值不變。
事實證明,在測試階段,當我們評估一個神經網絡時,也就是用綠線框標注的反向隨機失活方法,使測試階段變得更容易,因為它的數據擴展問題變少,我們將在下節課討論。
據我了解,目前實施dropout最常用的方法就是Inverted dropout,建議大家動手實踐一下。Dropout早期的迭代版本都沒有除以keep-prob,所以在測試階段,平均值會變得越來越復雜,不過那些版本已經不再使用了。
現在你使用的是向量,你會發現,不同的訓練樣本,清除不同的隱藏單元也不同。實際上,如果你通過相同訓練集多次傳遞數據,每次訓練數據的梯度不同,則隨機對不同隱藏單元歸零,有時卻并非如此。比如,需要將相同隱藏單元歸零,第一次迭代梯度下降時,把一些隱藏單元歸零,第二次迭代梯度下降時,也就是第二次遍歷訓練集時,對不同類型的隱藏層單元歸零。向量或用來決定第三層中哪些單元歸零,無論用foreprop還是backprop,這里我們只介紹了foreprob。
如何在測試階段訓練算法,在測試階段,我們已經給出了,或是想預測的變量,用的是標準計數法。我用,第0層的激活函數標注為測試樣本,我們在測試階段不使用dropout函數,尤其是像下列情況:
以此類推直到最后一層,預測值為。
顯然在測試階段,我們并未使用dropout,自然也就不用拋硬幣來決定失活概率,以及要消除哪些隱藏單元了,因為在測試階段進行預測時,我們不期望輸出結果是隨機的,如果測試階段應用dropout函數,預測會受到干擾。理論上,你只需要多次運行預測處理過程,每一次,不同的隱藏單元會被隨機歸零,預測處理遍歷它們,但計算效率低,得出的結果也幾乎相同,與這個不同程序產生的結果極為相似。
Inverted dropout函數在除以keep-prob時可以記住上一步的操作,目的是確保即使在測試階段不執行dropout來調整數值范圍,激活函數的預期結果也不會發生變化,所以沒必要在測試階段額外添加尺度參數,這與訓練階段不同。
這就是dropout,大家可以通過本周的編程練習來執行這個函數,親身實踐一下。
為什么dropout會起作用呢?下節課我們將更加直觀地了解dropout的具體功能。
1.7 理解 dropout(Understanding Dropout)
Dropout可以隨機刪除網絡中的神經單元,他為什么可以通過正則化發揮如此大的作用呢?
直觀上理解:不要依賴于任何一個特征,因為該單元的輸入可能隨時被清除,因此該單元通過這種方式傳播下去,并為單元的四個輸入增加一點權重,通過傳播所有權重,dropout將產生收縮權重的平方范數的效果,和之前講的正則化類似;實施dropout的結果實它會壓縮權重,并完成一些預防過擬合的外層正則化;對不同權重的衰減是不同的,它取決于激活函數倍增的大小。
總結一下,dropout的功能類似于正則化,與正則化不同的是應用方式不同會帶來一點點小變化,甚至更適用于不同的輸入范圍。
第二個直觀認識是,我們從單個神經元入手,如圖,這個單元的工作就是輸入并生成一些有意義的輸出。通過dropout,該單元的輸入幾乎被消除,有時這兩個單元會被刪除,有時會刪除其它單元,就是說,我用紫色圈起來的這個單元,它不能依靠任何特征,因為特征都有可能被隨機清除,或者說該單元的輸入也都可能被隨機清除。我不愿意把所有賭注都放在一個節點上,不愿意給任何一個輸入加上太多權重,因為它可能會被刪除,因此該單元將通過這種方式積極地傳播開,并為單元的四個輸入增加一點權重,通過傳播所有權重,dropout將產生收縮權重的平方范數的效果,和我們之前講過的正則化類似,實施dropout的結果是它會壓縮權重,并完成一些預防過擬合的外層正則化。
事實證明,dropout被正式地作為一種正則化的替代形式,對不同權重的衰減是不同的,它取決于倍增的激活函數的大小。
總結一下,dropout的功能類似于正則化,與正則化不同的是,被應用的方式不同,dropout也會有所不同,甚至更適用于不同的輸入范圍。
實施dropout的另一個細節是,這是一個擁有三個輸入特征的網絡,其中一個要選擇的參數是keep-prob,它代表每一層上保留單元的概率。所以不同層的keep-prob也可以變化。第一層,矩陣是7×3,第二個權重矩陣是7×7,第三個權重矩陣是3×7,以此類推,是最大的權重矩陣,因為擁有最大參數集,即7×7,為了預防矩陣的過擬合,對于這一層,我認為這是第二層,它的keep-prob值應該相對較低,假設是0.5。對于其它層,過擬合的程度可能沒那么嚴重,它們的keep-prob值可能高一些,可能是0.7,這里是0.7。如果在某一層,我們不必擔心其過擬合的問題,那么keep-prob可以為1,為了表達清除,我用紫色線筆把它們圈出來,每層keep-prob的值可能不同。
注意keep-prob的值是1,意味著保留所有單元,并且不在這一層使用dropout,對于有可能出現過擬合,且含有諸多參數的層,我們可以把keep-prob設置成比較小的值,以便應用更強大的dropout,有點像在處理正則化的正則化參數,我們嘗試對某些層施行更多正則化,從技術上講,我們也可以對輸入層應用dropout,我們有機會刪除一個或多個輸入特征,雖然現實中我們通常不這么做,keep-prob的值為1,是非常常用的輸入值,也可以用更大的值,或許是0.9。但是消除一半的輸入特征是不太可能的,如果我們遵守這個準則,keep-prob會接近于1,即使你對輸入層應用dropout。
總結一下,如果你擔心某些層比其它層更容易發生過擬合,可以把某些層的keep-prob值設置得比其它層更低,缺點是為了使用交叉驗證,你要搜索更多的超級參數,另一種方案是在一些層上應用dropout,而有些層不用dropout,應用dropout的層只含有一個超級參數,就是keep-prob。
結束前分享兩個實施過程中的技巧,實施dropout,在計算機視覺領域有很多成功的第一次。計算視覺中的輸入量非常大,輸入太多像素,以至于沒有足夠的數據,所以dropout在計算機視覺中應用得比較頻繁,有些計算機視覺研究人員非常喜歡用它,幾乎成了默認的選擇,但要牢記一點,dropout是一種正則化方法,它有助于預防過擬合,因此除非算法過擬合,不然我是不會使用dropout的,所以它在其它領域應用得比較少,主要存在于計算機視覺領域,因為我們通常沒有足夠的數據,所以一直存在過擬合,這就是有些計算機視覺研究人員如此鐘情于dropout函數的原因。直觀上我認為不能概括其它學科。
dropout一大缺點就是代價函數不再被明確定義,每次迭代,都會隨機移除一些節點,如果再三檢查梯度下降的性能,實際上是很難進行復查的。定義明確的代價函數每次迭代后都會下降,因為我們所優化的代價函數實際上并沒有明確定義,或者說在某種程度上很難計算,所以我們失去了調試工具來繪制這樣的圖片。我通常會關閉dropout函數,將keep-prob的值設為1,運行代碼,確保J函數單調遞減。然后打開dropout函數,希望在dropout過程中,代碼并未引入bug。我覺得你也可以嘗試其它方法,雖然我們并沒有關于這些方法性能的數據統計,但你可以把它們與dropout方法一起使用。
1.8 其他正則化方法(Other regularization methods)
除了正則化和隨機失活(dropout)正則化,還有幾種方法可以減少神經網絡中的過擬合:
一.數據擴增(數據增強)
假設你正在擬合貓咪圖片分類器,如果你想通過擴增訓練數據來解決過擬合,但擴增數據代價高,而且有時候我們無法擴增數據,但我們可以通過添加這類圖片來增加訓練集。例如,水平翻轉圖片,并把它添加到訓練集。所以現在訓練集中有原圖,還有翻轉后的這張圖片,所以通過水平翻轉圖片,訓練集則可以增大一倍,因為訓練集有冗余,這雖然不如我們額外收集一組新圖片那么好,但這樣做節省了獲取更多貓咪圖片的花費。
除了水平翻轉圖片,你也可以隨意裁剪圖片,這張圖是把原圖旋轉并隨意放大后裁剪的,仍能辨別出圖片中的貓咪。
通過隨意翻轉和裁剪圖片,我們可以增大數據集,額外生成假訓練數據。和全新的,獨立的貓咪圖片數據相比,這些額外的假的數據無法包含像全新數據那么多的信息,但我們這么做基本沒有花費,代價幾乎為零,除了一些對抗性代價。以這種方式擴增算法數據,進而正則化數據集,減少過擬合比較廉價。
像這樣人工合成數據的話,我們要通過算法驗證,圖片中的貓經過水平翻轉之后依然是貓。大家注意,我并沒有垂直翻轉,因為我們不想上下顛倒圖片,也可以隨機選取放大后的部分圖片,貓可能還在上面。
對于光學字符識別,我們還可以通過添加數字,隨意旋轉或扭曲數字來擴增數據,把這些數字添加到訓練集,它們仍然是數字。為了方便說明,我對字符做了強變形處理,所以數字4看起來是波形的,其實不用對數字4做這么夸張的扭曲,只要輕微的變形就好,我做成這樣是為了讓大家看的更清楚。實際操作的時候,我們通常對字符做更輕微的變形處理。因為這幾個4看起來有點扭曲。所以,數據擴增可作為正則化方法使用,實際功能上也與正則化相似。
二.early stopping
還有另外一種常用的方法叫作early stopping,運行梯度下降時,我們可以繪制訓練誤差,或只繪制代價函數的優化過程,在訓練集上用0-1記錄分類誤差次數。呈單調下降趨勢,如圖。
因為在訓練過程中,我們希望訓練誤差,代價函數都在下降,通過early stopping,我們不但可以繪制上面這些內容,還可以繪制驗證集誤差,它可以是驗證集上的分類誤差,或驗證集上的代價函數,邏輯損失和對數損失等,你會發現,驗證集誤差通常會先呈下降趨勢,然后在某個節點處開始上升,early stopping的作用是,你會說,神經網絡已經在這個迭代過程中表現得很好了,我們在此停止訓練吧,得到驗證集誤差,它是怎么發揮作用的?
當你還未在神經網絡上運行太多迭代過程的時候,參數接近0,因為隨機初始化值時,它的值可能都是較小的隨機值,所以在你長期訓練神經網絡之前依然很小,在迭代過程和訓練過程中的值會變得越來越大,比如在這兒,神經網絡中參數的值已經非常大了,所以early stopping要做就是在中間點停止迭代過程,我們得到一個值中等大小的弗羅貝尼烏斯范數,與正則化相似,選擇參數w范數較小的神經網絡,但愿你的神經網絡過度擬合不嚴重。
術語early stopping代表提早停止訓練神經網絡,訓練神經網絡時,我有時會用到early stopping,但是它也有一個缺點,我們來了解一下。
我認為機器學習過程包括幾個步驟,其中一步是選擇一個算法來優化代價函數,我們有很多種工具來解決這個問題,如梯度下降,后面我會介紹其它算法,例如Momentum,RMSprop和Adam等等,但是優化代價函數之后,我也不想發生過擬合,也有一些工具可以解決該問題,比如正則化,擴增數據等等。
在機器學習中,超級參數激增,選出可行的算法也變得越來越復雜。我發現,如果我們用一組工具優化代價函數,機器學習就會變得更簡單,在重點優化代價函數時,你只需要留意和,的值越小越好,你只需要想辦法減小這個值,其它的不用關注。然后,預防過擬合還有其他任務,換句話說就是減少方差,這一步我們用另外一套工具來實現,這個原理有時被稱為“正交化”。思路就是在一個時間做一個任務,后面課上我會具體介紹正交化,如果你還不了解這個概念,不用擔心。
但對我來說early stopping的主要缺點就是你不能獨立地處理這兩個問題,因為提早停止梯度下降,也就是停止了優化代價函數,因為現在你不再嘗試降低代價函數,所以代價函數的值可能不夠小,同時你又希望不出現過擬合,你沒有采取不同的方式來解決這兩個問題,而是用一種方法同時解決兩個問題,這樣做的結果是我要考慮的東西變得更復雜。
如果不用early stopping,另一種方法就是正則化,訓練神經網絡的時間就可能很長。我發現,這導致超級參數搜索空間更容易分解,也更容易搜索,但是缺點在于,你必須嘗試很多正則化參數的值,這也導致搜索大量值的計算代價太高。
Early stopping的優點是,只運行一次梯度下降,你可以找出的較小值,中間值和較大值,而無需嘗試正則化超級參數的很多值。
如果你還不能完全理解這個概念,沒關系,下節課我們會詳細講解正交化,這樣會更好理解。
雖然正則化有缺點,可還是有很多人愿意用它。吳恩達老師個人更傾向于使用正則化,嘗試許多不同的值,假設你可以負擔大量計算的代價。而使用early stopping也能得到相似結果,還不用嘗試這么多值。
這節課我們講了如何使用數據擴增,以及如何使用early stopping降低神經網絡中的方差或預防過擬合。
1.9 歸一化輸入(Normalizing inputs)
訓練神經網絡,其中一個加速訓練的方法就是歸一化輸入。假設一個訓練集有兩個特征,輸入特征為2維,歸一化需要兩個步驟:
零均值
歸一化方差;
我們希望無論是訓練集和測試集都是通過相同的μ和σ定義的數據轉換,這兩個是由訓練集得出來的。
第一步是零均值化,,它是一個向量,等于每個訓練數據?減去,意思是移動訓練集,直到它完成零均值化。
第二步是歸一化方差,注意特征的方差比特征的方差要大得多,我們要做的是給賦值,,這是節點?的平方,是一個向量,它的每個特征都有方差,注意,我們已經完成零值均化,元素就是方差,我們把所有數據除以向量,最后變成上圖形式。
和的方差都等于1。提示一下,如果你用它來調整訓練數據,那么用相同的?μ?和?來歸一化測試集。尤其是,你不希望訓練集和測試集的歸一化有所不同,不論μ的值是什么,也不論的值是什么,這兩個公式中都會用到它們。所以你要用同樣的方法調整測試集,而不是在訓練集和測試集上分別預估μ?和?。因為我們希望不論是訓練數據還是測試數據,都是通過相同μ和定義的相同數據轉換,其中μ和是由訓練集數據計算得來的。
我們為什么要這么做呢?為什么我們想要歸一化輸入特征,回想一下右上角所定義的代價函數。
如果你使用非歸一化的輸入特征,代價函數會像這樣:
這是一個非常細長狹窄的代價函數,你要找的最小值應該在這里。但如果特征值在不同范圍,假如取值范圍從1到1000,特征的取值范圍從0到1,結果是參數和值的范圍或比率將會非常不同,這些數據軸應該是和,但直觀理解,我標記為和,代價函數就有點像狹長的碗一樣,如果你能畫出該函數的部分輪廓,它會是這樣一個狹長的函數。
然而如果你歸一化特征,代價函數平均起來看更對稱,如果你在上圖這樣的代價函數上運行梯度下降法,你必須使用一個非常小的學習率。因為如果是在這個位置,梯度下降法可能需要多次迭代過程,直到最后找到最小值。但如果函數是一個更圓的球形輪廓,那么不論從哪個位置開始,梯度下降法都能夠更直接地找到最小值,你可以在梯度下降法中使用較大步長,而不需要像在左圖中那樣反復執行。
當然,實際上是一個高維向量,因此用二維繪制并不能正確地傳達并直觀理解,但總地直觀理解是代價函數會更圓一些,而且更容易優化,前提是特征都在相似范圍內,而不是從1到1000,0到1的范圍,而是在-1到1范圍內或相似偏差,這使得代價函數優化起來更簡單快速。
實際上如果假設特征范圍在0-1之間,的范圍在-1到1之間,范圍在1-2之間,它們是相似范圍,所以會表現得很好。
當它們在非常不同的取值范圍內,如其中一個從1到1000,另一個從0到1,這對優化算法非常不利。但是僅將它們設置為均化零值,假設方差為1,就像上一張幻燈片里設定的那樣,確保所有特征都在相似范圍內,通常可以幫助學習算法運行得更快。
所以如果輸入特征處于不同范圍內,可能有些特征值從0到1,有些從1到1000,那么歸一化特征值就非常重要了。如果特征值處于相似范圍內,那么歸一化就不是很重要了。執行這類歸一化并不會產生什么危害,我通常會做歸一化處理,雖然我不確定它能否提高訓練或算法速度。
這就是歸一化特征輸入,下節課我們將繼續討論提升神經網絡訓練速度的方法。
1.10 梯度消失/梯度爆炸(Vanishing / Exploding gradients)
訓練神經網絡,尤其是深度神經所面臨的一個問題就是梯度消失或梯度爆炸,也就是你訓練神經網絡的時候,導數或坡度有時會變得非常大,或者非常小,甚至于以指數方式變小,這加大了訓練的難度。
這節課,你將會了解梯度消失或梯度爆炸的真正含義,以及如何更明智地選擇隨機初始化權重,從而避免這個問題。假設你正在訓練這樣一個極深的神經網絡,為了節約幻燈片上的空間,我畫的神經網絡每層只有兩個隱藏單元,但它可能含有更多,但這個神經網絡會有參數,,等等,直到,為了簡單起見,假設我們使用激活函數,也就是線性激活函數,我們忽略,假設=0,如果那樣的話,輸出,如果你想考驗我的數學水平,,因為,所以我想,,因為我們使用了一個線性激活函數,它等于,所以第一項,通過推理,你會得出,因為,還等于,可以用替換,所以這一項就等于,這個就是()。
所有這些矩陣數據傳遞的協議將給出而不是的值。
假設每個權重矩陣,從技術上來講,最后一項有不同維度,可能它就是余下的權重矩陣,,因為我們假設所有矩陣都等于它,它是1.5倍的單位矩陣,最后的計算結果就是,也就是等于。如果對于一個深度神經網絡來說值較大,那么的值也會非常大,實際上它呈指數級增長的,它增長的比率是,因此對于一個深度神經網絡,的值將爆炸式增長。
相反的,如果權重是0.5,,它比1小,這項也就變成了,矩陣,再次忽略,因此每個矩陣都小于1,假設和都是1,激活函數將變成,,,,,等,直到最后一項變成,所以作為自定義函數,激活函數的值將以指數級下降,它是與網絡層數數量相關的函數,在深度網絡中,激活函數以指數級遞減。
我希望你得到的直觀理解是,權重只比1略大一點,或者說只是比單位矩陣大一點,深度神經網絡的激活函數將爆炸式增長,如果比1略小一點,可能是。
在深度神經網絡中,激活函數將以指數級遞減,雖然我只是討論了激活函數以與相關的指數級數增長或下降,它也適用于與層數相關的導數或梯度函數,也是呈指數級增長或呈指數遞減。
對于當前的神經網絡,假設,最近Microsoft對152層神經網絡的研究取得了很大進展,在這樣一個深度神經網絡中,如果激活函數或梯度函數以與相關的指數增長或遞減,它們的值將會變得極大或極小,從而導致訓練難度上升,尤其是梯度指數小于時,梯度下降算法的步長會非常非常小,梯度下降算法將花費很長時間來學習。
總結一下,我們講了深度神經網絡是如何產生梯度消失或爆炸問題的,實際上,在很長一段時間內,它曾是訓練深度神經網絡的阻力,雖然有一個不能徹底解決此問題的解決方案,但是已在如何選擇初始化權重問題上提供了很多幫助。
1.11 神經網絡的權重初始化(Weight Initialization for Deep NetworksVanishing / Exploding gradients)
上節課,我們學習了深度神經網絡如何產生梯度消失和梯度爆炸問題,最終針對該問題,我們想出了一個不完整的解決方案,雖然不能徹底解決問題,卻很有用,有助于我們為神經網絡更謹慎地選擇隨機初始化參數,為了更好地理解它,我們先舉一個神經單元初始化地例子,然后再演變到整個深度網絡。
我們來看看只有一個神經元的情況,然后才是深度網絡。
單個神經元可能有4個輸入特征,從到,經過處理,最終得到,稍后講深度網絡時,這些輸入表示為,暫時我們用表示。
,,暫時忽略,為了預防值過大或過小,你可以看到越大,你希望越小,因為是的和,如果你把很多此類項相加,希望每項值更小,最合理的方法就是設置,表示神經元的輸入特征數量,實際上,你要做的就是設置某層權重矩陣,就是我喂給第層神經單元的數量(即第層神經元數量)。
結果,如果你是用的是Relu激活函數,而不是,方差設置為,效果會更好。你常常發現,初始化時,尤其是使用Relu激活函數時,,它取決于你對隨機變量的熟悉程度,這是高斯隨機變量,然后乘以它的平方根,也就是引用這個方差。這里,我用的是,因為本例中,邏輯回歸的特征是不變的。但一般情況下層上的每個神經元都有個輸入。如果激活函數的輸入特征被零均值和標準方差化,方差是1,也會調整到相似范圍,這就沒解決問題(梯度消失和爆炸問題)。但它確實降低了梯度消失和爆炸問題,因為它給權重矩陣設置了合理值,你也知道,它不能比1大很多,也不能比1小很多,所以梯度沒有爆炸或消失過快。
我提到了其它變體函數,剛剛提到的函數是Relu激活函數,一篇由Herd等人撰寫的論文曾介紹過。對于幾個其它變體函數,如tanh激活函數,有篇論文提到,常量1比常量2的效率更高,對于tanh函數來說,它是,這里平方根的作用與這個公式作用相同(),它適用于tanh激活函數,被稱為Xavier初始化。Yoshua Bengio和他的同事還提出另一種方法,你可能在一些論文中看到過,它們使用的是公式。其它理論已對此證明,但如果你想用Relu激活函數,也就是最常用的激活函數,我會用這個公式,如果使用tanh函數,可以用公式,有些作者也會使用這個函數。
實際上,我認為所有這些公式只是給你一個起點,它們給出初始化權重矩陣的方差的默認值,如果你想添加方差,方差參數則是另一個你需要調整的超級參數,可以給公式添加一個乘數參數,調優作為超級參數激增一份子的乘子參數。有時調優該超級參數效果一般,這并不是我想調優的首要超級參數,但我發現調優過程中產生的問題,雖然調優該參數能起到一定作用,但考慮到相比調優,其它超級參數的重要性,我通常把它的優先級放得比較低。
希望你現在對梯度消失或爆炸問題以及如何為權重初始化合理值已經有了一個直觀認識,希望你設置的權重矩陣既不會增長過快,也不會太快下降到0,從而訓練出一個權重或梯度不會增長或消失過快的深度網絡。我們在訓練深度網絡時,這也是一個加快訓練速度的技巧。
1.12 梯度的數值逼近(Numerical approximation of gradients)
在實施backprop時,有一個測試叫做梯度檢驗,它的作用是確保backprop正確實施。因為有時候,你雖然寫下了這些方程式,卻不能100%確定,執行backprop的所有細節都是正確的。為了逐漸實現梯度檢驗,我們首先說說如何計算梯度的數值逼近,下節課,我們將討論如何在backprop中執行梯度檢驗,以確保backprop正確實施。
我們先畫出函數,標記為,,先看一下的值,假設,不增大的值,而是在?右側,設置一個,在左側,設置。因此,,,跟以前一樣,的值為0.01,看下這個小三角形,計算高和寬的比值,就是更準確的梯度預估,選擇函數在上的這個點,用這個較大三角形的高比上寬,技術上的原因我就不詳細解釋了,較大三角形的高寬比值更接近于的導數,把右上角的三角形下移,好像有了兩個三角形,右上角有一個,左下角有一個,我們通過這個綠色大三角形同時考慮了這兩個小三角形。所以我們得到的不是一個單邊公差而是一個雙邊公差。
我們寫一下數據算式,圖中綠色三角形上邊的點的值是,下邊的點是,這個三角形的高度是,這兩個寬度都是ε,所以三角形的寬度是,高寬比值為,它的期望值接近,傳入參數值,,大家可以暫停視頻,用計算器算算結果,結果應該是3.0001,而前面一張幻燈片上面是,當時,,所以這兩個值非常接近,逼近誤差為0.0001,前一張幻燈片,我們只考慮了單邊公差,即從到之間的誤差,的值為3.0301,逼近誤差是0.03,不是0.0001,所以使用雙邊誤差的方法更逼近導數,其結果接近于3,現在我們更加確信,可能是導數的正確實現,在梯度檢驗和反向傳播中使用該方法時,最終,它與運行兩次單邊公差的速度一樣,實際上,我認為這種方法還是非常值得使用的,因為它的結果更準確。
這是一些你可能比較熟悉的微積分的理論,如果你不太明白我講的這些理論也沒關系,導數的官方定義是針對值很小的,導數的官方定義是,如果你上過微積分課,應該學過無窮盡的定義,我就不在這里講了。
對于一個非零的,它的逼近誤差可以寫成,ε值非常小,如果,,大寫符號的含義是指逼近誤差其實是一些常量乘以,但它的確是很準確的逼近誤差,所以大寫的常量有時是1。然而,如果我們用另外一個公式逼近誤差就是,當小于1時,實際上比大很多,所以這個公式近似值遠沒有左邊公式的準確,所以在執行梯度檢驗時,我們使用雙邊誤差,即,而不使用單邊公差,因為它不夠準確。
如果你不理解上面兩條結論,所有公式都在這兒,不用擔心,如果你對微積分和數值逼近有所了解,這些信息已經足夠多了,重點是要記住,雙邊誤差公式的結果更準確,下節課我們做梯度檢驗時就會用到這個方法。
今天我們講了如何使用雙邊誤差來判斷別人給你的函數,是否正確實現了函數的偏導,現在我們可以使用這個方法來檢驗反向傳播是否得以正確實施,如果不正確,它可能有bug需要你來解決。
1.13 梯度檢驗(Gradient checking)
梯度檢驗幫我們節省了很多時間,也多次幫我發現backprop實施過程中的bug,接下來,我們看看如何利用它來調試或檢驗backprop的實施是否正確。
假設你的網絡中含有下列參數,和……和,為了執行梯度檢驗,首先要做的就是,把所有參數轉換成一個巨大的向量數據,你要做的就是把矩陣轉換成一個向量,把所有矩陣轉換成向量之后,做連接運算,得到一個巨型向量,該向量表示為參數,代價函數是所有和的函數,現在你得到了一個的代價函數(即)。接著,你得到與和順序相同的數據,你同樣可以把和……和轉換成一個新的向量,用它們來初始化大向量,它與具有相同維度。
同樣的,把轉換成矩陣,已經是一個向量了,直到把轉換成矩陣,這樣所有的都已經是矩陣,注意與具有相同維度,與具有相同維度。經過相同的轉換和連接運算操作之后,你可以把所有導數轉換成一個大向量,它與具有相同維度,現在的問題是和代價函數的梯度或坡度有什么關系?
這就是實施梯度檢驗的過程,英語里通常簡稱為“grad check”,首先,我們要清楚是超參數的一個函數,你也可以將J函數展開為,不論超級參數向量的維度是多少,為了實施梯度檢驗,你要做的就是循環執行,從而對每個也就是對每個組成元素計算的值,我使用雙邊誤差,也就是
只對增加,其它項保持不變,因為我們使用的是雙邊誤差,對另一邊做同樣的操作,只不過是減去,其它項全都保持不變。
從上節課中我們了解到這個值()應該逼近=,是代價函數的偏導數,然后你需要對i的每個值都執行這個運算,最后得到兩個向量,得到的逼近值,它與具有相同維度,它們兩個與具有相同維度,你要做的就是驗證這些向量是否彼此接近。
具體來說,如何定義兩個向量是否真的接近彼此?我一般做下列運算,計算這兩個向量的距離,的歐幾里得范數,注意這里()沒有平方,它是誤差平方之和,然后求平方根,得到歐式距離,然后用向量長度歸一化,使用向量長度的歐幾里得范數。分母只是用于預防這些向量太小或太大,分母使得這個方程式變成比率,我們實際執行這個方程式,可能為,使用這個取值范圍內的,如果你發現計算方程式得到的值為或更小,這就很好,這就意味著導數逼近很有可能是正確的,它的值非常小。
如果它的值在范圍內,我就要小心了,也許這個值沒問題,但我會再次檢查這個向量的所有項,確保沒有一項誤差過大,可能這里有bug。
如果左邊這個方程式結果是,我就會擔心是否存在bug,計算結果應該比小很多,如果比大很多,我就會很擔心,擔心是否存在bug。這時應該仔細檢查所有項,看是否有一個具體的值,使得與大不相同,并用它來追蹤一些求導計算是否正確,經過一些調試,最終結果會是這種非常小的值(),那么,你的實施可能是正確的。
在實施神經網絡時,我經常需要執行foreprop和backprop,然后我可能發現這個梯度檢驗有一個相對較大的值,我會懷疑存在bug,然后開始調試,調試,調試,調試一段時間后,我得到一個很小的梯度檢驗值,現在我可以很自信的說,神經網絡實施是正確的。
現在你已經了解了梯度檢驗的工作原理,它幫助我在神經網絡實施中發現了很多bug,希望它對你也有所幫助。
1.14 梯度檢驗應用的注意事項(Gradient Checking Implementation Notes)
這節課,分享一些關于如何在神經網絡實施梯度檢驗的實用技巧和注意事項。
首先,不要在訓練中使用梯度檢驗,它只用于調試。我的意思是,計算所有值的是一個非常漫長的計算過程,為了實施梯度下降,你必須使用和?backprop來計算,并使用backprop來計算導數,只要調試的時候,你才會計算它,來確認數值是否接近。完成后,你會關閉梯度檢驗,梯度檢驗的每一個迭代過程都不執行它,因為它太慢了。
第二點,如果算法的梯度檢驗失敗,要檢查所有項,檢查每一項,并試著找出bug,也就是說,如果與dθ[i]的值相差很大,我們要做的就是查找不同的i值,看看是哪個導致與的值相差這么多。舉個例子,如果你發現,相對某些層或某層的或的值相差很大,但是的各項非常接近,注意的各項與和的各項都是一一對應的,這時,你可能會發現,在計算參數的導數的過程中存在bug。反過來也是一樣,如果你發現它們的值相差很大,的值與的值相差很大,你會發現所有這些項目都來自于或某層的,可能幫你定位bug的位置,雖然未必能夠幫你準確定位bug的位置,但它可以幫助你估測需要在哪些地方追蹤bug。
第三點,在實施梯度檢驗時,如果使用正則化,請注意正則項。如果代價函數,這就是代價函數的定義,等于與相關的函數的梯度,包括這個正則項,記住一定要包括這個正則項。
第四點,梯度檢驗不能與dropout同時使用,因為每次迭代過程中,dropout會隨機消除隱藏層單元的不同子集,難以計算dropout在梯度下降上的代價函數。因此dropout可作為優化代價函數的一種方法,但是代價函數J被定義為對所有指數極大的節點子集求和。而在任何迭代過程中,這些節點都有可能被消除,所以很難計算代價函數。你只是對成本函數做抽樣,用dropout,每次隨機消除不同的子集,所以很難用梯度檢驗來雙重檢驗dropout的計算,所以我一般不同時使用梯度檢驗和dropout。如果你想這樣做,可以把dropout中的keepprob設置為1.0,然后打開dropout,并寄希望于dropout的實施是正確的,你還可以做點別的,比如修改節點丟失模式確定梯度檢驗是正確的。實際上,我一般不這么做,我建議關閉dropout,用梯度檢驗進行雙重檢查,在沒有dropout的情況下,你的算法至少是正確的,然后打開dropout。
最后一點,也是比較微妙的一點,現實中幾乎不會出現這種情況。當和接近0時,梯度下降的實施是正確的,在隨機初始化過程中……,但是在運行梯度下降時,和變得更大。可能只有在和接近0時,backprop的實施才是正確的。但是當和變大時,它會變得越來越不準確。你需要做一件事,我不經常這么做,就是在隨機初始化過程中,運行梯度檢驗,然后再訓練網絡,和會有一段時間遠離0,如果隨機初始化值比較小,反復訓練網絡之后,再重新運行梯度檢驗。
這就是梯度檢驗,恭喜大家,這是本周最后一課了。回顧這一周,我們講了如何配置訓練集,驗證集和測試集,如何分析偏差和方差,如何處理高偏差或高方差以及高偏差和高方差并存的問題,如何在神經網絡中應用不同形式的正則化,如正則化和dropout,還有加快神經網絡訓練速度的技巧,最后是梯度檢驗。這一周我們學習了很多內容,你可以在本周編程作業中多多練習這些概念。祝你好運,期待下周再見。
參考資料
[1]
深度學習課程:?https://mooc.study.163.com/university/deeplearning_ai
[2]黃海廣:?https://github.com/fengdu78
[3]github:?https://github.com/fengdu78/deeplearning_ai_books
總結
以上是生活随笔為你收集整理的深度学习笔记第二门课 改善深层神经网络 第一周:深度学习的实践层面的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深度学习笔记第一门课第四周:深层神经网
- 下一篇: 深度学习笔记第三门课 结构化机器学习项目