0

我問了一個關於我一直在建設的網絡的問題last week,,我重複了那些讓我發現幾個問題的建議。我已經回到這個項目,並解決了所有問題,並在此過程中瞭解了更多關於CNN的很多。現在我遇到了一個問題,就是我的所有權重都轉移到了大量的負值,這與RELU在輸出圖像中總是以完全黑色結束(使分類器無法完成它的工作)相關。卷積網絡過濾器總是負面的

在2個標記圖像:

enter image description here enter image description here

這些被傳遞到兩個層網絡,一個分類器(其自身得到100%)和一個過濾器3×3的卷積層。

在第一次迭代來自卷積層的輸出如下所示(以與上述順序相同的圖像):

enter image description here enter image description here

該過濾器是3 * 3 * 3中,由於圖像是RGB。權重都是0.0f-1.0f之間的隨機數。在下一次迭代中,圖像完全是黑色,打印過濾器顯示它們現在處於-49678.5f(我能看到的最高)和-61932.3f的範圍內。

這個問題反過來是由於交叉(標籤0,預測0)的Logistic迴歸/線性層瘋狂高的梯度傳回。對於圓圈(標籤1,預測0),值大致在-12和-5之間,但對於十字架,它們都處於正高1000到高2000範圍內。

,它發送這些後面的代碼看起來是這樣(部分省略):

void LinearClassifier::Train(float * x,float output, float y) 
{ 
    float h = output - y; 
    float average = 0.0f; 
    for (int i =1; i < m_NumberOfWeights; ++i) 
    { 
     float error = h*x[i-1]; 
     m_pGradients[i-1] = error; 
     average += error; 
    } 

    average /= static_cast<float>(m_NumberOfWeights-1); 

    for (int theta = 1; theta < m_NumberOfWeights; ++theta) 
    { 
     m_pWeights[theta] = m_pWeights[theta] - learningRate*m_pGradients[theta-1]; 
    } 

    // Bias 
    m_pWeights[0] -= learningRate*average; 
} 

這被傳遞迴單卷積層:

// This code is in three nested for loops (for layer,for outWidth, for outHeight) 
float gradient = 0.0f; 
// ReLu Derivative 
if (m_pOutputBuffer[outputIndex] > 0.0f) 
{ 
    gradient = outputGradients[outputIndex]; 
} 

for (int z = 0; z < m_InputDepth; ++z) 
{ 
    for (int u = 0; u < m_FilterSize; ++u) 
    { 
     for (int v = 0; v < m_FilterSize; ++v) 
     { 
      int x = outX + u - 1; 
      int y = outY + v - 1; 

      int inputIndex = x + y*m_OutputWidth + z*m_OutputWidth*m_OutputHeight; 

      int kernelIndex = u + v*m_FilterSize + z*m_FilterSize*m_FilterSize; 

      m_pGradients[inputIndex] += m_Filters[layer][kernelIndex]*gradient; 
      m_GradientSum[layer][kernelIndex] += input[inputIndex]*gradient; 
     } 
    } 
} 

該代碼是通過使遍歷每個圖像一次一個地呈現。漸變顯然是朝着正確的方向發展,但是如何阻止巨大的漸變投擲預測函數?

回答

2

RELU激活因此而臭名昭着。你通常不得不使用低學習率。這背後的原因是,當RELU返回正數時,它可以繼續自由學習,但是當一個單位返回一個非常低的數字時,它可能會變成一個「死亡」的神經元,並且不會再次激活。如果您有一個系統,其中正數可以自由改變,但低於某個閾值的負數可能會「卡住」,如果達到此最小閾值,系統最終會完全卡住。

RELU神經元也初始化您的重量是非常微妙的。看起來你正在初始化範圍0-1,這產生了巨大的偏見。這裏有兩個技巧 - 使用以0爲中心的範圍,並且範圍要小得多。像(-0.1) - (0。1)

另一件事是,根據我的經驗,RELU單位似乎在難度較大的任務(如Imagenet分類)中更有用。給TanH單位試試這個。你初始化權重和學習速度的方式並不那麼微妙。

0

我通過縮小CNN層中的漸變來修復它,但現在我很困惑,爲什麼這個工作/是需要的,所以如果有人有任何直覺,爲什麼這個工程將是偉大的。