卷积网络过滤器总是负面的

时间:2016-02-11 20:18:14

标签: c++ machine-learning neural-network logistic-regression backpropagation

我问了一个关于我正在构建last week,的网络的问题,我重复了一些建议,这些建议导致我发现了一些问题。我已经回到这个项目并修复了所有问题,并在此过程中学习了很多关于CNN的知识。现在我陷入了一个问题,我的所有权重都转移到大量的负值,再加上输出图像中的RELU端总是完全是黑色的(这使分类器无法完成它的工作) )。

在两张带标签的图片上:

enter image description here enter image description here

这些传递到一个双层网络,一个分类器(自己100%获得)和一个过滤器3 * 3卷积层。

在第一次迭代中,conv层的输出看起来像(图像的顺序与上面相同):

enter image description here enter image description here

由于图像为RGB,滤镜为3 * 3 * 3。权重都是0.0f-1.0f之间的随机数。在下一次迭代中,图像完全黑色,打印过滤器显示它们现在的范围是-49678.5f(我能看到的最高值)和-61932.3f。

这个问题反过来是由于从Logistic回归/线性层传递回来的梯度是十字架的疯狂高(标签0,预测0)。对于圆(标签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 个答案:

答案 0 :(得分:3)

RELU激活因此而臭名昭着。您通常必须使用较低的学习率。这背后的原因是,当RELU返回正数时,它可以继续自由学习,但当一个单位返回一个非常低的数字时,它可以变成一个“死”的数字。神经元,永远不再激活。如果你有一个系统,其中正数可以自由改变,但负数低于某个阈值有可能被卡住,如果达到这个最小阈值,系统最终将完全停滞。

使用RELU神经元初始化你的体重非常微妙。您似乎正在初始化到0-1范围,这会产生巨大的偏差。这里有两个提示 - 使用一个以0为中心的范围,以及一个小得多的范围。类似于(-0.1) - (0.1)

另一件事是,根据我的经验,RELU单元似乎在困难的任务(如Imagenet分类)中更有用。为TanH单位试一试。初始化权重和学习率的方式几乎不那么精致。

答案 1 :(得分:0)

我通过缩小CNN层中的渐变来修复它,但现在我很困惑为什么这个工作/需要,所以如果有人有任何直觉,为什么这个工作是伟大的。