首页 文章

反向传播用于整流线性单元激活与交叉熵误差

提问于
浏览 1116
7

我正在尝试使用反向传播实现神经网络的梯度计算 . 我无法使用交叉熵误差和纠正线性单位(ReLU)作为激活 .

我设法通过sigmoid,tanh和ReLU激活函数使我的实现工作为平方错误 . 正确计算具有S形激活梯度的交叉熵(CE)误差 . 但是,当我将激活更改为ReLU时 - 它失败了 . (我正在为CE跳过tanh,因为它在(-1,1)范围内抽取值 . )

是否因为log函数的行为接近于0(ReLU在归一化输入时约为50%的时间返回)?我试图通过以下方式解决这个问题:

log(max(y,eps))

但它只能帮助将误差和渐变带回实数 - 它们仍然与数值梯度不同 .

我使用数值梯度验证结果:

num_grad = (f(W+epsilon) - f(W-epsilon)) / (2*epsilon)

以下matlab代码提供了我的实验中使用的简化和压缩反向传播实现:

function [f, df] = backprop(W, X, Y)
% W - weights
% X - input values
% Y - target values

act_type='relu';    % possible values: sigmoid / tanh / relu
error_type = 'CE';  % possible values: SE / CE

N=size(X,1); n_inp=size(X,2); n_hid=100; n_out=size(Y,2);
w1=reshape(W(1:n_hid*(n_inp+1)),n_hid,n_inp+1);
w2=reshape(W(n_hid*(n_inp+1)+1:end),n_out, n_hid+1);

% feedforward
X=[X ones(N,1)];
z2=X*w1'; a2=act(z2,act_type); a2=[a2 ones(N,1)];
z3=a2*w2'; y=act(z3,act_type);

if strcmp(error_type, 'CE')   % cross entropy error - logistic cost function
    f=-sum(sum( Y.*log(max(y,eps))+(1-Y).*log(max(1-y,eps)) ));
else % squared error
    f=0.5*sum(sum((y-Y).^2));
end

% backprop
if strcmp(error_type, 'CE')   % cross entropy error
    d3=y-Y;
else % squared error
    d3=(y-Y).*dact(z3,act_type);
end

df2=d3'*a2;
d2=d3*w2(:,1:end-1).*dact(z2,act_type);
df1=d2'*X;

df=[df1(:);df2(:)];

end

function f=act(z,type) % activation function
switch type
    case 'sigmoid'
        f=1./(1+exp(-z));
    case 'tanh'
        f=tanh(z);
    case 'relu'
        f=max(0,z);
end
end

function df=dact(z,type) % derivative of activation function
switch type
    case 'sigmoid'
        df=act(z,type).*(1-act(z,type));
    case 'tanh'
        df=1-act(z,type).^2;
    case 'relu'
        df=double(z>0);
end
end

Edit

经过另一轮实验,我发现在最后一层使用softmax:

y=bsxfun(@rdivide, exp(z3), sum(exp(z3),2));

和softmax成本函数:

f=-sum(sum(Y.*log(y)));

使实现适用于所有激活功能,包括ReLU .

这使我得出结论,后勤成本函数(二元分类器)不适用于ReLU:

f=-sum(sum( Y.*log(max(y,eps))+(1-Y).*log(max(1-y,eps)) ));

但是,我仍然无法弄清问题所在 .

4 回答

  • 2

    每个压扁函数sigmoid,tanh和softmax(在输出层中)意味着不同的成本函数 . 然后理解RLU(在输出层中)与交叉熵成本函数不匹配 . 我将尝试一个简单的平方误差成本函数来测试RLU输出层 .

    RLU的真正力量在于深网的隐藏层,因为它不会受到梯度消失的影响 .

  • 0

    如果使用渐变后代,则需要派生激活函数,以便稍后在反向传播方法中使用 . 你确定'df = double(z> 0)'吗?对于物流和tanh似乎是对的 .

    此外,你确定这个'd3 = y-Y'?我会说当你使用逻辑函数而不是ReLu时这是正确的(导数不相同,因此不会导致那个简单的等式) .

    您可以使用softplus函数,它是ReLU的平滑版本,其衍生物是众所周知的(逻辑函数) .

  • 0

    我认为这个缺陷在于与数值计算的衍生物共同构成 . 在你的derivativeActivation函数中,你将ReLu的导数定义为0为0.在数值上计算x = 0处的导数时,它表示为(ReLU(x epsilon)-ReLU(x-epsilon)/(2 * epsilon) )在x = 0时为0.5 . 因此,将x = 0处的ReLU的导数定义为0.5将解决该问题

  • 0

    我以为我会分享我遇到类似问题的经历 . 我也设计了我的多分类器 ANN ,所有隐藏层都使用 RELU 作为非线性激活函数,输出层使用 softmax 函数 .

    我的问题在某种程度上与我正在使用的编程语言/平台的数值精度有关 . 在我的情况下,我注意到,如果我使用"plain" RELU 它不仅会杀死渐变,而且我使用的编程语言产生了以下 softmax 输出向量(这只是一个示例示例):

    ⎡1.5068230536681645e-35⎤
    ⎢ 2.520367499064734e-18⎥
    ⎢3.2572859518007807e-22⎥
    ⎢                     1⎥
    ⎢ 5.020155103452967e-32⎥
    ⎢1.7620297760773188e-18⎥
    ⎢ 5.216008990667109e-18⎥
    ⎢ 1.320937038894421e-20⎥
    ⎢2.7854159049317976e-17⎥
    ⎣1.8091246170996508e-35⎦
    

    请注意,大多数元素的值接近 0 ,但最重要的是注意输出中的 1 值 .

    我使用了与您使用的错误函数不同的 cross-entropy 错误函数 . 而不是计算 log(max(1-y, eps)) 我坚持基本 log(1-y) . 所以考虑到上面的输出向量,当我计算 log(1-y) 时,由于 cross-entropy ,我得到了 -Inf ,这显然杀死了算法 .

    我想如果你的 eps 不够合理,以至于 log(max(1-y, eps)) - > log(max(0, eps)) 不会产生太小的输出 log 输出你可能会像我一样在类似的泡菜中 .

    我对这个问题的解决方案是使用Leaky RELU . 一旦我开始使用它,我就可以继续使用多分类器 cross-entropy 来反对你决定尝试的功能 .

相关问题