日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

深度学习与计算机视觉系列(7)_神经网络数据预处理,正则化与损失函数

發布時間:2025/3/21 pytorch 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深度学习与计算机视觉系列(7)_神经网络数据预处理,正则化与损失函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:寒小陽?&&?龍心塵?
時間:2016年1月。?
出處:?
http://blog.csdn.net/han_xiaoyang/article/details/50451460?
http://blog.csdn.net/longxinchen_ml/article/details/50451493?
聲明:版權所有,轉載請聯系作者并注明出處

1. 引言

上一節我們講完了各種激勵函數的優缺點和選擇,以及網絡的大小以及正則化對神經網絡的影響。這一節我們講一講輸入數據以及損失函數設定的一些事情。

2. 數據與網絡的設定

前一節提到前向計算涉及到的組件(主要是神經元)設定。神經網絡結構和參數設定完畢之后,我們就得到得分函數/score function(忘記的同學們可以翻看一下之前的博文),總體說來,一個完整的神經網絡就是在不斷地進行線性映射(權重和input的內積)和非線性映射(部分激勵函數作用)的過程。這一節我們會展開來講講數據預處理權重初始化損失函數的事情。

2.1 數據預處理

在卷積神經網處理圖像問題的時候,圖像數據有3種常見的預處理可能會用到,如下。我們假定數據表示成矩陣為X,其中我們假定X是[N*D]維矩陣(N是樣本數據量,D為單張圖片的數據向量長度)。

  • 去均值,這是最常見的圖片數據預處理,簡單說來,它做的事情就是,對待訓練的每一張圖片的特征,都減去全部訓練集圖片的特征均值,這么做的直觀意義就是,我們把輸入數據各個維度的數據都中心化到0了。使用python的numpy工具包,這一步可以用X -= np.mean(X, axis = 0)輕松實現。當然,其實這里也有不同的做法:簡單一點,我們可以直接求出所有像素的均值,然后每個像素點都減掉這個相同的值;稍微優化一下,我們在RGB三個顏色通道分別做這件事。
  • 歸一化,歸一化的直觀理解含義是,我們做一些工作去保證所有的維度上數據都在一個變化幅度上。通常我們有兩種方法來實現歸一化。一個是在數據都去均值之后,每個維度上的數據都除以這個維度上數據的標準差(X /= np.std(X, axis = 0))。另外一種方式是我們除以數據絕對值最大值,以保證所有的數據歸一化后都在-1到1之間。多說一句,其實在任何你覺得各維度幅度變化非常大的數據集上,你都可以考慮歸一化處理。不過對于圖像而言,其實這一步反倒可做可不做,因為大家都知道,像素的值變化區間都在[0,255]之間,所以其實圖像輸入數據天生幅度就是一致的。

上述兩個操作對于數據的作用,畫成示意圖,如下:?

  • PCA和白化/whitening,這是另外一種形式的數據預處理。在經過去均值操作之后,我們可以計算數據的協方差矩陣,從而可以知道數據各個維度之間的相關性,簡單示例代碼如下:
<code class="language-python hljs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 假定輸入數據矩陣X是[N*D]維的</span> X -= np.mean(X, axis = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 去均值</span> cov = np.dot(X.T, X) / X.shape[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 計算協方差</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

得到的結果矩陣中元素(i,j)表示原始數據中,第i維和第j維直接愛你的相關性。有意思的是,其實協方差矩陣的對角線包含了每個維度的變化幅度。另外,我們都知道協方差矩陣是對稱的,我們可以在其上做矩陣奇異值分解(SVD factorization):

<code class="language-python hljs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">U,S,V = np.linalg.svd(cov)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

其中U為特征向量,我們如果相對原始數據(去均值之后)做去相關操作,只需要進行如下運算:

<code class="language-python hljs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">Xrot = np.dot(X, U)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

這么理解一下可能更好,U是一組正交基向量。所以我們可以看做把原始數據X投射到這組維度保持不變的正交基底上,從而也就完成了對原始數據的去相關。如果去相關之后你再求一下Xrot的協方差矩陣,你會發現這時候的協方差矩陣是一個對角矩陣了。而numpy中的np.linalg.svd更好的一個特性是,它返回的U是對特征值排序過的,這也就意味著,我們可以用它進行降維操作。我們可以只取top的一些特征向量,然后做和原始數據做矩陣乘法,這個時候既降維減少了計算量,同時又保存下了絕大多數的原始數據信息,這就是所謂的主成分分析/PCA

<code class="language-python hljs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">Xrot_reduced = np.dot(X, U[:,:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>])</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

這個操作之后,我們把原始數據集矩陣從[N*D]降維到[N*100],保存了前100個能包含絕大多數數據信息的維度。實際應用中,你在PCA降維之后的數據集上,做各種機器學習的訓練,在節省空間和時間的前提下,依舊能有很好的訓練準確度。

最后我們再提一下whitening操作。所謂whitening,就是把各個特征軸上的數據除以特征向量,從而達到在每個特征軸上都歸一化幅度的結果。whitening變換的幾何意義和理解是,如果輸入的數據是多變量高斯,那whitening之后的 數據是一個均值為0而不同方差的高斯矩陣。這一步簡單代碼實現如下:

<code class="language-python hljs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">#白化數據</span> Xwhite = Xrot / np.sqrt(S + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1e-5</span>)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

提個醒:whitening操作會有嚴重化噪聲的可能。注意到我們在上述代碼中,分母的部分加入了一個很小的數1e-5,以防止出現除以0的情況。但是數據中的噪聲部分可能會因whitening操作而變大,因為這個操作的本質是把輸入的每個維度都拉到差不多的幅度,那么本不相關的有微弱幅度變化的噪聲維度,也被拉到了和其他維度同樣的幅度。當然,我們適當提高墳墓中的安全因子(1e-5)可以在一定程度上緩解這個問題。

下圖為原始數據到去相關白化之后的數據分布示意圖:?

我們來看看真實數據集上的操作與得到的結果,也許能對這些過程有更清晰一些的認識。大家都還記得CIFAR-10圖像數據集吧。訓練集大小為50000*3072,也就是說,每張圖片都被展成一個3072維度的列向量了。然后我們對原始50000*3072數據矩陣做SVD分解,進行上述一些操作,再可視化一下,得到的結果示意圖如下:

我們稍加解釋一下,最左邊是49張原始圖片;左起第2幅圖是最3072個特征向量中最top的144個,這144個特征向量包含了絕大多數數據變量信息,而其實它們代表的是圖片中低頻的信息;左起第3幅圖表示PCA降維操作之后的49張圖片,使用上面求得的144個特征向量。我們可以觀察到圖片好像被蒙上了一層東西一樣,模糊化了,這也就表明了我們的top144個特征向量捕捉到的都是圖像的低頻信息,不過我們發現圖像的絕大多數信息確實被保留下來了;最右圖是whitening的144個數通過乘以U.transpose()[:144,:]還原回圖片的樣子,有趣的是,我們發現,現在低頻信息基本都被濾掉了,剩下一些高頻信息被放大呈現。

實際工程中,因為這個部分講到數據預處理,我們就把基本的幾種數據預處理都講了一遍,但實際卷積神經網中,我們并沒有用到去相關和whitening操作。當然,去均值是非常非常重要的,而每個像素維度的歸一化也是常用的操作。

特別說明,需要特別說明的一點是,上述的預處理操作,一定都是在訓練集上先預算的,然后應用在交叉驗證/測試集上的。舉個例子,有些同學會先把所有的圖片放一起,求均值,然后減掉均值,再把這份數據分作訓練集和測試集,這是不對的親!!!

2.2 權重初始化

我們之前已經看過一個完整的神經網絡,是怎么樣通過神經元和連接搭建起來的,以及如何對數據做預處理。在訓練神經網絡之前,我們還有一個任務要做,那就是初始化參數。

錯誤的想法:全部初始化為0,有些同學說,那既然要訓練和收斂嘛,初始值就隨便設定,簡單一點就全設為0好了。親,這樣是絕對不行的!!!為啥呢?我們在神經網絡訓練完成之前,是不可能預知神經網絡最后的權重具體結果的,但是根據我們歸一化后的數據,我們可以假定,大概有半數左右的權重是正數,而另外的半數是負數。但設定全部初始權重都為0的結果是,網絡中每個神經元都計算出一樣的結果,然后在反向傳播中有一樣的梯度結果,因此迭代之后的變化情況也都一樣,這意味著這個神經網絡的權重沒有辦法差異化,也就沒有辦法學習到東西。

很小的隨機數,其實我們依舊希望初始的權重是較小的數,趨于0,但是就像我們剛剛討論過的一樣,不要真的是0。綜合上述想法,在實際場景中,我們通常會把初始權重設定為非常小的數字,然后正負盡量一半一半。這樣,初始的時候權重都是不一樣的很小隨機數,然后迭代過程中不會再出現迭代一致的情況。舉個例子,我們可能可以這樣初始化一個權重矩陣W=0.0001*np.random.randn(D,H)。這個初始化的過程,使得每個神經元的權重向量初始化為多維高斯中的隨機采樣向量,所以神經元的初始權重值指向空間中的隨機方向。

特別說明:其實不一定更小的初始值會比大值有更好的效果。我們這么想,一個有著非常小的權重的神經網絡在后向傳播過程中,回傳的梯度也是非常小的。這樣回傳的”信號”流會相對也較弱,對于層數非常多的深度神經網絡,這也是一個問題,回傳到最前的迭代梯度已經很小了。

方差歸一化,上面提到的建議有一個小問題,對于隨機初始化的神經元參數下的輸出,其分布的方差隨著輸入的數量,會增長。我們實際上可以通過除以總輸入數目的平方根,歸一化每個神經元的輸出方差到1。也就是說,我們傾向于初始化神經元的權重向量為w = np.random.randn(n) / sqrt(n),其中n為輸入數。

我們從數學的角度,簡單解釋一下,為什么上述操作可以歸一化方差。考慮在激勵函數之前的權重w與輸入x的內積s=niwixi部分,我們計算一下s的方差:

Var(s)=Var(inwixi)=inVar(wixi)=in[E(wi)]2Var(xi)+E[(xi)]2Var(wi)+Var(xi)Var(wi)=inVar(xi)Var(wi)=(nVar(w))Var(x)

注意,這個推導的前2步用到了方差的性質。第3步我們假定輸入均值為0,因此E[xi]=E[wi]=0。不過這是我們的一個假設,實際情況下并不一定是這樣的,比如ReLU單元的均值就是正的。最后一步我們假定wi,xi是獨立分布。我們想讓s的方差和輸入x的方差一致,因此我們想讓w的方差取值為1/n,又因為我們有公式Var(aX)=a2Var(X),所以a應該取值為a=1/n???,numpy里的實現為w = np.random.randn(n) / sqrt(n)。

對于初始化權重還有一些類似的研究和建議,比如說Glorot在論文Understanding the difficulty of training deep feedforward neural networks就推薦使用能滿足Var(w)=2/(nin+nout)的權重初始化。其中nin,nout是前一層和后一層的神經元個數。而另外一篇比較新的論文Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification,則指出尤其對于ReLU神經元,我們初始化方差應該為2.0/n,也就是w = np.random.randn(n) * sqrt(2.0/n),目前的神經網絡中使用了很多ReLU單元,因此這個設定其實在實際應用中使用最多。

偏移量/bias初始化:相對而言,bias項初始化就簡單一些。我們很多時候簡單起見,直接就把它們都設為0.在ReLU單元中,有些同學會使用很小的數字(比如0.01)來代替0作為所有bias項的初始值,他們解釋說這樣也能保證ReLU單元一開始就是被激活的,因此反向傳播過程中不會終止掉回傳的梯度。不過似乎實際的實驗過程中,這個優化并不是每次都能起到作用的,因此很多時候我們還是直接把bias項都初始化為0。

2.3 正則化

在前一節里我們說了我們要通過正則化來控制神經網絡,使得它不那么容易過擬合。有幾種正則化的類型供選擇:

  • L2正則化,這個我們之前就提到過,非常常見。實現起來也很簡單,我們在損失函數里,加入對每個參數的懲罰度。也就是說,對于每個權重w,我們在損失函數里加入一項12λw2,其中λ是我們可調整的正則化強度。順便說一句,這里在前面加上1/2的原因是,求導/梯度的時候,剛好變成λw而不是2λw。L2正則化理解起來也很簡單,它對于特別大的權重有很高的懲罰度,以求讓權重的分配均勻一些,而不是集中在某一小部分的維度上。我們再想想,加入L2正則化項,其實意味著,在梯度下降參數更新的時候,每個權重以W += -lambda*W的程度被拉向0。

  • L1正則化,這也是一種很常見的正則化形式。在L1正則化中,我們對于每個權重w的懲罰項為λ|w|。有時候,你甚至可以看到大神們混著L1和L2正則化用,也就是說加入懲罰項λ1w+λ2w2,L1正則化有其獨特的特性,它會讓模型訓練過程中,權重特征向量逐漸地稀疏化,這意味著到最后,我們只留下了對結果影響最大的一部分權重,而其他不相關的輸入(例如『噪聲』)因為得不到權重被抑制。所以通常L2正則化后的特征向量是一組很分散的小值,而L1正則化只留下影響較大的權重。在實際應用中,如果你不是特別要求只保留部分特征,那么L2正則化通常能得到比L1正則化更好的效果

  • 最大范數約束,另外一種正則化叫做最大范數約束,它直接限制了一個上行的權重邊界,然后約束每個神經元上的權重都要滿足這個約束。實際應用中是這樣實現的,我們不添加任何的懲罰項,就按照正常的損失函數計算,只不過在得到每個神經元的權重向量w??之后約束它滿足w??2<c。有些人提到這種正則化方式幫助他們提高最后的模型效果。另外,這種正則化方式倒是有一點很吸引人:在神經網絡訓練學習率設定很高的時候,它也能很好地約束住權重更新變化,不至于直接掛掉。

  • Dropout,親,這個是我們實際神經網絡訓練中,用的非常多的一種正則化手段,同時也相當有效。Srivastava等人的論文Dropout: A Simple Way to Prevent Neural Networks from Overfitting最早提到用dropout這種方式作為正則化手段。一句話概括它,就是:在訓練過程中,我們對每個神經元,都以概率p保持它是激活狀態,1-p的概率直接關閉它。

下圖是一個3層的神經網絡的dropout示意圖:?


?

可以這么理解,在訓練過程中呢,我們對全體神經元,以概率p做了一個采樣,只有選出的神經元要進行參數更新。所以最后就從左圖的全連接到右圖的Dropout過后神經元連接圖了。需要多說一句的是,在測試階段,我們不用dropout,而是直接從概率的角度,對權重配以一個概率值。

簡單的Dropout代碼如下(這是簡易實現版本,但是不建議使用,我們會分析為啥,并在之后給出優化版):

<code class="language-python hljs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"> p = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.5</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 設定dropout的概率,也就是保持一個神經元激活狀態的概率</span><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">train_step</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(X)</span>:</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""" X contains the data """</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 3層神經網絡前向計算</span>H1 = np.maximum(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, np.dot(W1, X) + b1)U1 = np.random.rand(*H1.shape) < p <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 第一次Dropout</span>H1 *= U1 <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># drop!</span>H2 = np.maximum(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, np.dot(W2, H1) + b2)U2 = np.random.rand(*H2.shape) < p <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 第二次Dropout</span>H2 *= U2 <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># drop!</span>out = np.dot(W3, H2) + b3<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 反向傳播: 計算梯度... (這里省略)</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 參數更新... (這里省略)</span><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">predict</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(X)</span>:</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 加上Dropout之后的前向計算</span>H1 = np.maximum(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, np.dot(W1, X) + b1) * p H2 = np.maximum(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, np.dot(W2, H1) + b2) * p out = np.dot(W3, H2) + b3</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

上述代碼中,在train_step函數中,我們做了2次Dropout。我們甚至可以在輸入層做一次dropout。反向傳播過程保持不變,除了我們要考慮一下U1,U2

很重要的一點是,大家仔細看predict函數部分,我們不再dropout了,而是對于每個隱層的輸出,都用概率p做了一個幅度變換。可以從數學期望的角度去理解這個做法,我們考慮一個神經元的輸出為x(沒有dropout的情況下),它的輸出的數學期望為px+(1?p)0,那我們在測試階段,如果直接把每個輸出x都做變換xpx,其實是可以保持一樣的數學期望的。

上述代碼的寫法有一些缺陷,我們必須在測試階段對每個神經的輸出都以p的概率輸出。考慮到實際應用中,測試階段對于時間的要求非常高,我們可以考慮反著來,代碼實現的時候用inverted dropout,即在訓練階段就做相反的幅度變換/scaling(除以p),這樣在測試階段,我們可以直接把權重拿來使用,而不用附加很多步用p做scaling的過程。inverted dropout的示例代碼如下:

<code class="language-python hljs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""" Inverted Dropout的版本,把本該花在測試階段的時間,轉移到訓練階段,從而提高testing部分的速度 """</span>p = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.5</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># dropout的概率,也就是保持一個神經元激活狀態的概率</span><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">train_step</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(X)</span>:</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># f3層神經網絡前向計算</span>H1 = np.maximum(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, np.dot(W1, X) + b1)U1 = (np.random.rand(*H1.shape) < p) / p <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 注意到這個dropout中我們除以p,做了一個inverted dropout</span>H1 *= U1 <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># drop!</span>H2 = np.maximum(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, np.dot(W2, H1) + b2)U2 = (np.random.rand(*H2.shape) < p) / p <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 這個dropout中我們除以p,做了一個inverted dropout</span>H2 *= U2 <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># drop!</span>out = np.dot(W3, H2) + b3<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 反向傳播: 計算梯度... (這里省略)</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 參數更新... (這里省略)</span><span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">def</span> <span class="hljs-title" style="box-sizing: border-box;">predict</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(X)</span>:</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"># 直接前向計算,無需再乘以p</span>H1 = np.maximum(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, np.dot(W1, X) + b1) H2 = np.maximum(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, np.dot(W2, H1) + b2)out = np.dot(W3, H2) + b3</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li></ul>

對于dropout這個部分如果你有更深的興趣,歡迎閱讀以下文獻:?
* 2014 Srivastava 的論文Dropout paper?
*?Dropout Training as Adaptive Regularization

  • bias項的正則化,其實我們在之前的博客中提到過,我們大部分時候并不對偏移量項做正則化,因為它們也沒有和數據直接有乘法等交互,也就自然不會影響到最后結果中某個數據維度的作用。不過如果你愿意對它做正則化,倒也不會影響最后結果,畢竟總共有那么多權重項,才那么些bias項,所以一般也不會影響結果。

實際應用中:我們最常見到的是,在全部的交叉驗證集上使用L2正則化,同時我們在每一層之后用dropout,很常見的dropout概率為p=0.5,你也可以通過交叉驗證去調整這個值。

2.4 損失函數

剛才討論了數據預處理、權重初始化與正則化相關的問題。現在我們回到訓練需要的關鍵之一:損失函數。對于這么復雜的神經網絡,我們也得有一個評估準則去評估預測值和真實結果之間的吻合度,也就是損失函數。神經網絡里的損失函數,實際上是計算出了每個樣本上的loss,再求平均之后的一個形式,即L=1NiLi,其中N是訓練樣本數。

2.4.1 分類問題

  • 分類問題是到目前為止我們一直在討論的。我們假定一個數據集中每個樣本都有唯一一個正確的標簽/類別。我們之前提到過有兩種損失函數可以使用,其一是SVM的hinge loss:

Li=jyimax(0,fj?fyi+1)

另外一個是Softmax分類器中用到的互熵損失:

Li=?log??efyijefj??

  • 問題:特別多的類別數。當類別標簽特別特別多的時候(比如ImageNet包含22000個類別),層次化的Softmax,它將類別標簽建成了一棵樹,這樣任何一個類別,其實就對應tree的一條路徑,然后我們在每個樹的結點上都訓練一個Softmax以區分是左分支還是右分支。

  • 屬性分類,上述的兩種損失函數都假定,對于每個樣本,我們只有一個正確的答案yi。但是在有些場景下,yi是一個二值的向量,每個元素都代表有沒有某個屬性,這時候我們怎么辦呢?舉個例子說,Instagram上的圖片可以看作一大堆hashtag里的一個tag子集,所有一張圖片可以有多個tag。對于這種情況,大家可能會想到一個最簡單的處理方法,就是對每個屬性值都建一個二分類的分類器。比如,對應某個類別的二分類器可能有如下形式的損失函數:

Li=jmax(0,1?yijfj)

其中的求和是針對有所的類別j,而yij是1或者-1(取決于第i個樣本是否有第j個屬性的標簽),打分向量fj在類別/標簽被預測到的情況下為正,其他情況為負。注意到如果正樣本有比+1小的得分,或者負樣本有比-1大的得分,那么損失/loss就一直在累積。

另外一個也許有效的解決辦法是,我們可以對每個屬性,都單獨訓練一個邏輯回歸分類器,一個二分類的邏輯回歸分類器只有0,1兩個類別,屬于1的概率為:

P(y=1x;w,b)=11+e?(wTx+b)=σ(wTx+b)

又因為0,1兩類的概率和為1,所以歸屬于類別0的概率為P(y=0x;w,b)=1?P(y=1x;w,b)。一個樣本在σ(wTx+b)>0.5的情況下被判定為1,對應sigmoid函數化簡一下,對應的是得分wTx+b>0。這時候的損失函數可以定義為最大化似然概率的形式,也就是:

Li=jyijlog(σ(fj))+(1?yij)log(1?σ(fj))

其中標簽yij為1(正樣本)或者0(負樣本),而δ是sigmoid函數。

2.4.2 回歸問題

回歸是另外一類機器學習問題,主要用于預測連續值屬性,比如房子的價格或者圖像中某些東西的長度等。對于回歸問題,我們一般計算預測值和實際值之間的差值,然后再求L2范數或者L1范數用于衡量。其中對一個樣本(一張圖片)計算的L2范數損失為:

Li=f?yi22

而L1范數損失函數是如下的形式:?

Li=f?yi1=jfj?(yi)j

注意

  • 回歸問題中用到的L2范數損失,比分類問題中的Softmax分類器用到的損失函數,更難優化。直觀想一想這個問題,一個神經網絡最后輸出離散的判定類別,比訓練它去輸出一個個和樣本結果對應的連續值,要簡單多了。
  • 另外一個,前面的博文中提到過,其實Softmax這種分類器,對于輸出的打分結果具體值是不怎么在乎的,它只在乎各個類別之間的打分幅度有沒有差很多(比如二分類兩個類別的得分是1和9,與0.1和0.9)。
  • 再一個,L2范數損失健壯性更差一些,異常點和噪聲都可能改變損失函數的幅度,而帶來大的梯度偏差。
  • 一般情況下,對于回歸問題,我們都會首先考慮,這個問題能否轉化成對應的分類問題,比如說我們把輸出值劃分成不同的區域(切成一些桶)。舉個例子,如果我們要預測一個產品的預測打分,我們可以考慮把得分結果分成1-5顆星,而轉化成一個分類問題。
  • 如果你覺得問題確實沒辦法轉化成分類問題,那要小心使用L2范數損失:舉個例子,在神經網絡中,在L2損失函數之前使用dropout是不合適的。

如果我們遇到回歸問題,首先要想想,是否完全沒有可能把結果離散化之后,把這個問題轉化成一個分類問題。

3. 總結

總結一下:

  • 在很多神經網絡的問題中,我們都建議對數據特征做預處理,去均值,然后歸一化到[-1,1]之間。
  • 從一個標準差為2/n???的高斯分布中初始化權重,其中n為輸入的個數。
  • 使用L2正則化(或者最大范數約束)和dropout來減少神經網絡的過擬合。
  • 對于分類問題,我們最常見的損失函數依舊是SVM hinge loss和Softmax互熵損失。

總結

以上是生活随笔為你收集整理的深度学习与计算机视觉系列(7)_神经网络数据预处理,正则化与损失函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 一级片一区 | 国产中文在线视频 | 韩国电影一区二区三区 | 天堂а√在线中文在线新版 | 看黄免费网站 | 看个毛片 | 日韩一级不卡 | 玖玖爱精品 | 777777av| 亚洲国产极品 | 在线观看污网站 | 日本高潮网站 | 男人和女人做爽爽视频 | 裸体美女免费视频网站 | 国产一区二区不卡在线 | 国产自在线 | 黄网站免费在线观看 | 国产馆视频 | 国产在线精品一区 | 国产一级久久久 | 日韩欧美少妇 | 久久网站av| 国产中文字幕在线视频 | 亚洲精品网站在线 | 国产成人免费在线观看 | 国产三级国产精品 | jiz亚洲| 91美女网站| 非洲黑人狂躁日本妞 | 高清亚洲| 五月婷婷激情五月 | 国产99在线观看 | 日本少妇毛茸茸高潮 | 特大黑人巨交吊性xxxxhd | 日本成人精品视频 | 久久av免费看 | 天堂在线8 | 国产在线传媒 | 日本在线免费观看视频 | 中文字幕一区二区三区人妻电影 | 欧美日韩亚洲国产另类 | 综合亚洲视频 | 91九色视频在线观看 | 亚洲视频91 | 免费在线观看亚洲 | 蜜臀精品 | 国产xxxx做受性欧美88 | 欧美日韩黄色一级片 | 中文字幕免费观看 | 变态另类ts人妖一区二区 | 双性人妖互交localhost | 国产在线观看免费网站 | 毛片网站网址 | 大奶一区| 伊人精品在线视频 | 色666 | xfplay5566色资源网站 | 羞羞色院91蜜桃 | 韩国伦理在线视频 | 黄色一级大片在线免费看国产一 | 好妞色妞国产在线视频 | 黑巨茎大战欧美白妞 | 亚洲第一福利网站 | 福利在线视频观看 | 91精品人妻一区二区三区蜜桃欧美 | 韩日中文字幕 | 精品人妻在线视频 | 男人天堂成人 | 日本高清一区二区视频 | 黑人操日本女人视频 | 污污视频在线观看网站 | 给我看免费高清在线观看 | 日本亚洲色大成网站www久久 | 黄色录像二级片 | 日韩视频在线观看免费视频 | 欧美一级少妇 | 日本色婷婷| 亚洲av综合永久无码精品天堂 | 日韩激情在线播放 | 欧美老女人性视频 | av在线免费观看一区 | 欧美在线观看a | 手机看片国产 | 人人舔人人爽 | 久操视频网站 | 人妻少妇偷人精品视频 | 国产成人一区二区三区别 | 婷婷啪啪 | 亚洲欧美一区二区三区不卡 | 自拍偷拍国产视频 | av老司机在线观看 | 三上悠亚人妻中文字幕在线 | 国产日韩片 | 色女生影院 | 一级黄色片免费播放 | 国产一极片 | 亚洲图片欧美日韩 | 韩日a级片 | 国产一区麻豆 |