# 吳恩達老師_深度學習_改善深度神經網路_第一週_深度學習的實用層面 ###### tags: `deep learning` `Andrew Ng` `改善深度神經網路` ## Train/dev/test sets ![](https://i.imgur.com/IHQeOFA.jpg) **課程說明**:在配置三個資料集過程中做出好的決策 ![](https://i.imgur.com/jA1hDbD.jpg) 在執行深度學習的時候需要做很多的選擇,像隱藏層需要幾層、隱藏單元需要多少、學習效率設置、啟動函數選擇... 但這類超參數的設置我們不會一開始就能確定,需要透過多次迭代過程驗證確認。 目前而言,深度學習在多個領域上得到了廣大的對用,即使是領域上的專家,從一個領域得來的直覺經驗通常無法轉移到其它應用領域。因為這牽扯到的相關因素太多了,也因此即使是經驗豐富的深度學習專家也不大可能一開始就可以預設出最佳超參數。 所以說,深度學習的應用是一個迭代過程。 ![](https://i.imgur.com/XSFiPH2.jpg) 規劃資料集也是過程中的一個重點! 資料集通常會拆分三份,訓練、驗證、測試,接下來會對訓練集做訓練,透過驗證選擇最好的模型,經過充份驗證之後選擇最終模型做測試。 在小數據機器學習中通常的拆分為『70訓練/30測試』或『60訓練/20驗證/20測試』。 在大數據時代,擁有的數據集可能是百萬級別,這時候不需要用到20%做驗證,或許10000筆資料就足以做驗證,10000筆資料就足以做測試資料評估單個分類器。『98訓練/1驗證/1測試』『99.5訓練/0.25驗證/0.25測試』『99.5訓練/0.4驗證/0.1測試』 ![](https://i.imgur.com/9zJTH01.jpg) 目前深度學習愈來愈多人在訓練集與測試集分佈不匹配的情況下進行訓練! 假設要建置一個用戶可以上傳大量圖片的app,並且找出所有貓咪照片。 這時候,訓練集可能是網路上下載的貓咪照片,而驗證、測試是用戶透過這個app上傳的貓咪照片。 網路上抓下的貓咪照片可能都很專業、質量精美,而上傳的可能是手機拍攝,畫素並沒有那麼高。 這兩邊的資料是不相同不對等的,這種情況下建議『確保驗證集和測試集數據來自同一分佈』 最後,就算沒有測試集也沒有關係,測試集的目的是對最終選擇的模型做出有無偏差評估(unbiased estimate),所以,如果一個模型將資料集拆成兩份的時候,一份為訓練集,一份會稱為驗證集(train dev set not train test set)。 有效的拆分可以幫助我們驗證模型的偏差與方差,就可以幫助我們更高效的選擇合適的演算法。 ## Bias/Variance ![](https://i.imgur.com/VlTpt4E.jpg) **課程說明**:偏差與方差的權衡 ![](https://i.imgur.com/mogFMlu.jpg) 在二維空間上,我們才有辦法透過可視化來確認模型狀況。在更高維度上就需要利用其它方式來檢驗偏差與方差。 * high bias * 無法有效分類 * under fitting * just right * 恰如其分 * high variance * 過度擬合 * over fitting ![](https://i.imgur.com/9y79jp0.jpg) 通過檢查訓練資料集與驗證資料集我們就可以檢查模型狀況。 當訓練資料集的錯誤率僅1%而驗證資料集有11%的時候,即代表此模型過度擬合於訓練資料集(high variance)。 當訓練資料集的錯誤率為15%而驗證資料集亦有16%的時候,代表此模型或許狀況不是那麼好,那就是高偏差(high bias) 當訓練資料集的錯誤率為15%而驗證資料集達30%的時候,代表此模型有高偏差(high bias)也有高方差(high variance) 最後,訓練資料集有0.5%的錯誤,驗證資料集亦只有1%,那這模型或許就很不錯! :::info 最優誤差又稱為貝葉斯誤差(bayes error),接近0% ::: ![](https://i.imgur.com/iYlqove.jpg) 如果是高偏差又高方差的模型,就會如上圖般呈現。 ## Basic recipe for machine learning ![](https://i.imgur.com/ypw23MQ.jpg) **課程說明**:機器學習的基礎 ![](https://i.imgur.com/14ppge2.jpg) 在建立模型之後,首先確認是否有<font color=red>高偏差(high bias)</font>問題,或許加入更多隱藏層,或許使用更多隱藏單元,或許建立更大型的神經網路...等,至少模型需要可以擬合於訓練資料集。 有效降低偏差問題之後,再利用驗證資料集確認方差問題。若擁有高方差問題,可以引入更多的資料(如果有的話),或是透過正規化的方式處理。 :::info 高方差與高偏差的處理方式不同 ::: ## Regularization ![](https://i.imgur.com/KjpGJuO.jpg) **課程說明**:正規化原理 ![](https://i.imgur.com/GCRIUq3.jpg) 以logistic為例 $J(w,b)=\frac{1}{m}\sum^m_{i=1}L(\hat{y}^{(i)},y^{(i)})$ 其中w與b是logistic的兩個參數。 在logistic的成本函數中加入<font color=red>正規化參數$\lambda$</font> $J(w,b)=\frac{1}{m}\sum^m_{i=1}L(\hat{y}^{(i)},y^{(i)})+\frac{\lambda}{2m}||w||^2_2$ :::info b的部份加與不加對式子的影響不大,因為b只是一個個數,w所代表的是所有的參數,影響較多。 ::: * L1 * $\frac{\lambda}{m}\sum^{n}_{j=1}|w|=\frac{\lambda}{m}||w||_1$ * 造成稀疏矩陣 * w會有很多0 * L2 * $||w||^2_2=w的範數=\sum^{n}_{j=1}w^2_j=w^Tw$ * 愈來愈多人使用 我們會透過訓練資料集與驗證資料集的狀況來確認$\lambda$的選擇。 :::info 在python中會以lambd表示,因為lambda是保留字 ::: ![](https://i.imgur.com/2sUAfKX.jpg) 在神經網路中,我們一樣來看如何實現正規化 $J(w^{[1]},b^{[1]}...,w^{[m]},b^{[m]})=\frac{1}{m}\sum^m_{i=1}L(\hat{y}^{(i)},y^{(i)})+\frac{\lambda}{2m}\sum^L_{l=1}||w^{[l]}||^2_F$ $||w^{[l]}||^2$(矩陣範數)定義為每個元素的平方和=$\sum_i\sum_j(w^{[l]}_{ij})^2$=Frobenius norm(弗羅貝尼烏斯範數,代表矩陣中所有元素的平方和) $w=(n^{[l-1]},n^{[l]})$ 梯度下降的部份 $dw^{[l]}=反向傳播+\frac{\lambda}{m}w^{[l]}$ $w^{[l]}:=w^{[l]}-\alpha dw^{[l]}$ ## Why regularization reduces overfitting ![](https://i.imgur.com/JI2QMVS.jpg) **課程說明**:為何正規化可以避免過度擬合 ![](https://i.imgur.com/UiwTgiw.jpg) $J(w^{[l]},b^{[l]})=\frac{1}{m}\sum^m_{i=1}L(\hat{y}^{(i)},y^{(i)})+\frac{\lambda}{2m}\sum^L_{l=1}||w^{[l]}||^2_F$ 假設上面神經網路是過適的情況(高方差) 在$\lambda$設置夠大的時候,權重矩陣W會接近於0,藉著讓多數權重接近0來消除隱藏單元的影響。也會因此讓神經網路從複雜變的簡單如邏輯斯迴歸一樣,不同在於這網路夠深。 這並非消除了神經網路的隱藏單元,而是降低了它的影響性。 ![](https://i.imgur.com/0p73LqT.jpg) 為何正規化可以預防overfitting? 直觀來看,假設使用的啟動函數是tanh,即g(z)=tanh(z),$z^{[l]}=w^{[l]}a^{[l-1]}+b^{[l]}$ 在$\lambda$大的情況下,$w^{[l]}$會變小,相對的$z^{[l]}$也會變小,tanh函數就會落在中間段的線性部份,g(z)會大致呈現線性。 每一層都幾乎會是線性,如同線性迴歸一樣,整個神經網路就會是一個線性網路。即使是很深的神經網路,但是因為具有線性啟動函數的特徵,最終只能計算線性函數,不適合用於計算複雜的決策以及過度擬合數據的非線性決策邊界。 ## Dropout regularization ![](https://i.imgur.com/Z1btB1g.jpg) **課程說明**:Dropout ![](https://i.imgur.com/Crlir2o.jpg) 假設這個神經網路存在著過適的問題,透過dropout做正規化,流程如下: * 複製神經網路 * 設置消除神經網路中節點的概率 * 每個節點的保留與否各50%(超參數) * 消除節點 * 刪掉從該節點進出的連線 * 得到一個節點更少,規模更小的網路 * 利用反向傳播訓練 對每一個訓練樣本都以一個精簡之後的神經網路來訓練它,這看起來很奇怪,但是真的有效。 ![](https://i.imgur.com/Oi4ICtn.jpg) 實作dropout的方式有很多,最常用的是inverted dropout(反向隨機) 以L=3的神經網路,並且第3層有50個隱藏單元為例,a3=(50,m),實作流程如下: - [ ] 可補在notebook上的執行圖 * 設置一個向量$d3$ * d3=np.random.rand(a3.shape\[0],a3.shape\[1])<keep-prob * keep-prob:超參數,上節例為0.5,此例為0.8 * 代表消除任一隱藏單元的機率是0.2 * 隨機數值<0.8的為1,保留 * 隨機數值>0.8的為0,消除 * random.rand會隨機產生一個(a3.shape[0],a3.shape[1])的矩陣,數值為0~1 * 計算a3啟動函數 * a3=np.multply(a3,d3) * 元素相乘,效果等同於a3*=d3 * 利用上面的遮罩d3將等於0的元素過濾 * 元素為0的機率為20%,因為我們設置了0.8 * 因此被歸零的單元平均有10個 * a3除keep-prob * a3 /= keep-prob * 計算z4 * $z^{[4]}=w^{[4]}a^{[3]}+b^{[4]}$ * 這邊的a3是已經除過0.8的a3 * 有一種物品打8折之後再除8折,就是還原為1,主要是因為補回被歸零的20%神經單元 ![](https://i.imgur.com/SNy1sWo.jpg) 測試階段時通常不會使用dropout,這是因為在測試階段時我們不希望輸出結果是隨機的,如果在測試階段時使用,預測會受到干擾。 ## Understanding dropout ![](https://i.imgur.com/H38FpEx.jpg) **課程說明**:了解Dropout ![](https://i.imgur.com/yq1ymQL.jpg) 上小節提到,dropout隨機的消除了隱藏單元,產生一個較小的神經網路,這跟使用正規化的的效果是一樣的。 以輸出為例,透過dropout,四個隱藏單元會隨機的被刪除,也因此,輸出單元(紫色劃起來那個)沒辦法依靠任何輸入單元,因為任一輸入單元都可能被隨機刪除。 dropout會產生收縮權重的平方範數的效果,類似於L2正規化,會壓縮權重用以預防過適。 L2對不同權重的衰減不同,取決於倍增的激活函數大小。 應用dropout需設置另一個超參數keep-prob,它代表每一隱藏層上保留神經元的概率,針對每層的keep-prob可以有不同的設置。 以右下圖為例: w1=(3,7) w2=(7,7) w3=(7,3) 其中w2是最大的權重矩陣,為了避免過適,可以針對w2給予較多的消除,也許設置0.5,其它層也許0.7,其它後面較少神經單元的部份,也許可以給1(全部保留) 老師分享的兩個技巧: 很多機器視覺,影像處理喜歡使用,但是dropout是一種正規化方式,避免過適,所以除非過適,不然不會使用。 dropout一個很大的缺點就是成本函數J不再被明確的定義,也因此梯度下降很難確定有效過,所以在使用的時候會先設置keep-prob=1,確認成本函數有確實的降低之後再開啟keep-prob的設置。 ## Other regularization methos ![](https://i.imgur.com/QEPNgCk.jpg) **課程說明**:其它正規化方法 ![](https://i.imgur.com/45udMHy.jpg) 假設我們正在建置一個貓咪圖片分類器,並且有著過適的問題,但取得更多的資料集代價高,而且有時候無法取得更多資料。 這時候可以這麼做: * 將照片水平翻轉 * 局部放大剪裁 雖然只是原圖的變化,但是整體來說還是有幫助。 如果是光學文字的辨視,還可以將文字扭曲,稍微調整水平之後加入訓練集。 :::info 數據增加可以做為正規化方法使用 ::: ![](https://i.imgur.com/qfAWg5M.jpg) 另一種方式稱為early stopping 在利用曲線觀察訓練與驗證資料集的成本函數J下降狀況的時候會發現,通常驗證資料集會先呈現下降,接著在某個點往上,而early stopping的用意就是,在往上之前,我們停止訓練吧。 在未對神經網路迭代訓練之前,w是隨機初始值並且接近於0,隨著訓練過程過來愈長,w會愈來愈大,early sotpping做的就是在中間點停止迭代過程。 我們會得到一個w值中等大小的佛羅貝尼烏斯範數,與L2正規化相似。 以此方式的缺點在於,你無法獨立的處理優化成本函數與減少方差(這後續會有課程說明正交化),因為提早停止梯度下降,也就是停止優化成本函數J,所以我們用一個方法來同時處理兩問題(優化成本函數與減少方差) 優點即是,梯度下降只執行一次,不需像L2般嚐試很多超參數$\lambda$來測試 ## Normalizing inputs ![](https://i.imgur.com/D3SkfGN.jpg) **課程說明**:歸一化 ![](https://i.imgur.com/P7yMJBa.jpg) 假設我們的輸入有兩個特徵$x_1,x_2$,呈現散佈圖如上。 歸一化需要兩個步驟: * 零均值化 * $\mu=\frac{1}{m}\sum^m_{i=1}x^{(i)}$ * $x:=x-\mu$ * 會造成資料平均為0 * 中間圖 * 歸一化方差 * 此例來看,$x_1$的方差較$x_2$大 * 看分佈,$x_1$分佈較寬大 * $\sigma^2=\frac{1}{m}\sum^m_{i=1}x^{(i)}**2$ * $x/=\sigma^2$ * 右邊圖(兩特徵方差為1) * 用相同的數值去歸一化測試資料集 * 不是在測試資料集再算一次,因為我們要讓訓練集與測試集通過相同的定義做轉換 ![](https://i.imgur.com/BK2mEo0.jpg) 為何需要歸一化? 原始資料未執行歸一化之前,成本函數會是一個細長的圖示(左圖),而歸一化之後成本函數看起來會較為對稱(右圖)。 這對執行梯度下降來說很有差別,執行歸一化之後的梯度下降,不論你從那邊開始,都可以用較大的學習效率來執行,而未執行歸一化之前的梯度下降,你必需選擇較小的學習效率。 :::info 透過歸一化可以讓特徵在相似範圍內 ::: ## Vanishing/exploding gradents ![](https://i.imgur.com/dxYLVWy.jpg) **課程說明**:梯度消失/爆炸 ![](https://i.imgur.com/qPTzf08.jpg) 假設有一個很深的神經網路$w^{[L]}$,有兩個特徵,並且b=0,g(z)=z(代表為線性) $\hat{y}=w^{[L]}w^{[L-1]}w^{[L-2]}....w^{[3]}w^{[2]}w^{[1]}$ $z^{[1]}=w^{[1]}x$ $a^{[1]}=g(z^{[1]})=z^{[1]}$ $a^{[2]}=g(z^{[2]})=g(w^{[2]}a^{[1]})$ 以此類別 $a^{[3]}=g(z^{[3]})=g(w^{[3]}a^{[2]})$...(一路帶就會是老師寫的式子了) 假設每個權重矩陣w皆為單位矩陣 $w=\left[\begin{array}{ccc}1.5,0 \\0,1.5\end{array}\right]$ $\hat{y}=\left[\begin{array}{ccc}1.5,0 \\0,1.5\end{array}\right]^{[L-1]}x$ 就會造成$\hat{y}$以指數級成長,若w是0.5,那就會以指數級下降 題外話,最近微軟對152層神經網路的研究取得很大的進展。 ## Weight initialization for deep networks **課程說明**:權重初始化 ![](https://i.imgur.com/asvsfgz.jpg) 先看單一神經單元的案例 上例是四個輸入特徵,一個輸出的神經網路,並且b=0 $z=w_1x_1+w_2x_2+...w_nx_n$ 為了預防z過大或過小,當n愈大,我們會希望w愈小,一個方式,就是讓$w=\frac{1}{n}$ $w^l=np.random.randn(shape)*np.sqrt(1/n^{(l-1)})$ 各啟動函數應用 * 可以設置一個超參數(乘數參數來控制) * relu,使用$\frac{2}{n^{[l-1]}}$效果會更好。 * tanh,使用$\sqrt{\frac{1}{n^{[l-1]}}}$ * 稱為Xavier初始化 ## Numerical approximation of gradients ![](https://i.imgur.com/OORLi4X.jpg) **課程說明**:反向傳播梯度檢查,梯度數值逼近 ![](https://i.imgur.com/sYJWpT9.jpg) ![](https://i.imgur.com/iEK8zsr.jpg) 左圖是$f(\theta)=\theta^3$,假設$\theta=1$,並且在左右兩側各加入$\epsilon$為$\theta+\epsilon$,$\theta-\epsilon$,$\epsilon=0.01$ 以$\theta-\epsilon$至$\theta+\epsilon$做導數確認(大三角形),這看起來像是兩個小三角型($\theta-\epsilon$至$\theta$與$\theta-\epsilon$至$\theta+\epsilon$),我們通過大三角形同時考慮了兩個小三角形,因此我們得到的是一個雙邊公差,而不是單邊公差。 三角形的高為$f(\theta+\epsilon)-f(\theta-\epsilon)$ 三角型的寬為$2\epsilon$ 高寬比(斜率)為$\frac{f(\theta+\epsilon)-f(\theta-\epsilon)}{2\epsilon}\approx g(\theta)$ 套入公式計算$\frac{(1.01^3-(0.99)^3)}{2*0.01}=3.0001$ 上一節投影片中$g(\theta)=3\theta^2=3$ 這兩個數值非常接近,誤差為0.0001,如果只考慮單邊誤差的話,$g(\theta)$=3.0301,由此可以知道,雙邊驗證可以更接近導數值,也確認我們求出的數值3是正確的。 ## Gradient Checking ![](https://i.imgur.com/HBmgHkO.jpg) **課程說明**:梯度檢查 ![](https://i.imgur.com/QD7yvF8.jpg) 假設神經網路中有$W^{[1]},b^{[1]}..W^{[L]},b^{[L]}$ 檢查步驟: * 將所有參數(W,b)轉為一個巨大的向量 * 將各層W,b轉成向量之後再將各層w串接成一個巨型向量$\theta$ * $J(W^{[1]},b^{[1]}..W^{[L]},b^{[L]})=J(\theta)$ * 將所有參數導數(dw,db)轉為一個巨大的向量 * $dW^{[1]}與W^{[1]}$有相同的維度 * 同上一步驟產生一個巨型向量$d\theta$ ![](https://i.imgur.com/DiXKfvN.jpg) for each i: $d\theta_{approx}{[i]}=\frac{J(\theta_1,\theta_2...\theta_i+\epsilon+...)-J(\theta_1,\theta_2...\theta_i-\epsilon+...)}{2\epsilon} \approx d\theta{[1]}=\frac{dj}{d\theta i}$ 這邊要注意,迴圈中只對第i個元素做雙邊驗證 最後會得到一個$d\theta_{approx}$向量,與$d\theta$具相同維度,再驗證兩邊是否接近。 驗證方式: * $||d\theta_{approx}-d\theta||_2$(歐幾里德範數) * 沒有平方項,取誤差平方和之後求平方根得歐式距離 * 向量長度歸一化 * $\frac{||d\theta_{approx}-d\theta||_2}{||d\theta{approx}||_2+||d\theta||_2}$ * 分母用來預防向量過大、過小 * $\epsilon$設置 * 10的-7次方 * 計算結果 * 結果為10的-7次方或更小,這就很好 * 結果為10的-5次方就要注意,或許需要檢查一下 * 結果為10的-3次方就檢是否有bug了 ## Gradient Checking implementation notes ![](https://i.imgur.com/ApPDM2G.jpg) **課程說明**:實作梯度檢查的注意事項 ![](https://i.imgur.com/daOSryT.jpg) * 不要在訓練中使用梯度檢查,只用於debug * 施行梯度檢查非常耗資源 * 若$d\theta_{approx}$數值差異過大,需逐項檢查 * 若使用正規化,要記得正規項也要包在裡面 * 不能與dropout同時使用 * dropout會隨機消除神經單元,難以檢驗 * 初始化權重之後檢查梯度,並在訓練之後再次的檢查梯度