1

我在 MATLAB 中有这个反向传播实现,并且在训练它时遇到了问题。在训练阶段的早期,所有输出都变为 1。我已将输入数据(除了用于生成二进制目标向量的所需类)标准化为区间 [0, 1]。我一直在提到人工智能中的实现:一种现代方法,Norvig 等人。

根据我的代码检查了伪代码(并研究了一段时间的算法),我无法发现错误。我已经很久没有使用 MATLAB,所以一直在尝试在需要的地方使用文档。

我还尝试了隐藏层中不同数量的节点和不同的学习率(ALPHA)。

目标数据编码如下:当目标被分类为 时,2目标向量将是[0,1,0],假设它是1[1, 0, 0]依此类推。我还尝试对目标使用不同的值,例如 (for class 1for example) [0.5, 0, 0]

我注意到我的一些体重超过了1,导致净值很大。

%Topological constants
NUM_HIDDEN = 8+1;%written as n+1 so is clear bias is used
NUM_OUT = 3;

%Training constants
ALPHA = 0.01;
TARG_ERR = 0.01;
MAX_EPOCH = 50000;

%Read and normalize data file.
X = normdata(dlmread('iris.data'));
X = shuffle(X);
%X_test = normdata(dlmread('iris2.data'));
%epocherrors = fopen('epocherrors.txt', 'w');

%Weight matrices.
%Features constitute size(X, 2)-1, however size is (X, 2) to allow for
%appending bias.
w_IH = rand(size(X, 2), NUM_HIDDEN)-(0.5*rand(size(X, 2), NUM_HIDDEN)); 
w_HO = rand(NUM_HIDDEN+1, NUM_OUT)-(0.5*rand(NUM_HIDDEN+1, NUM_OUT));%+1 for bias

%Layer nets
net_H = zeros(NUM_HIDDEN, 1);
net_O = zeros(NUM_OUT, 1);

%Layer outputs
out_H = zeros(NUM_HIDDEN, 1);
out_O = zeros(NUM_OUT, 1);

%Layer deltas
d_H = zeros(NUM_HIDDEN, 1);
d_O = zeros(NUM_OUT, 1);

%Control variables
error = inf;
epoch = 0;

%Run the algorithm.
while error > TARG_ERR && epoch < MAX_EPOCH
    for n=1:size(X, 1)
        x = [X(n, 1:size(X, 2)-1) 1]';%Add bias for hiddens & transpose to column vector.
        o = X(n, size(X, 2));

        %Forward propagate.
        net_H = w_IH'*x;%Transposed w.
        out_H = [sigmoid(net_H); 1]; %Append 1 for bias to outputs
        net_O = w_HO'*out_H;
        out_O = sigmoid(net_O); %Again, transposed w.

        %Calculate output deltas.
        d_O = ((targetVec(o, NUM_OUT)-out_O) .* (out_O .* (1-out_O)));

        %Calculate hidden deltas.
        for i=1:size(w_HO, 1);
            delta_weight = 0;
            for j=1:size(w_HO, 2)
                delta_weight = delta_weight + d_O(j)*w_HO(i, j);
            end
            d_H(i) = (out_H(i)*(1-out_H(i)))*delta_weight;
        end

        %Update hidden-output weights
        for i=1:size(w_HO, 1)
            for j=1:size(w_HO, 2)
                w_HO(i, j) = w_HO(i, j) + (ALPHA*out_H(i)*d_O(j));
            end
        end

        %Update input-hidden weights.
        for i=1:size(w_IH, 1)
            for j=1:size(w_IH, 2)
                w_IH(i, j) = w_IH(i, j) + (ALPHA*x(i)*d_H(j));
            end
        end
        out_O
        o
        %out_H
        %w_IH
        %w_HO
        %d_O
        %d_H
    end  
end

function outs = sigmoid(nets)
    outs = zeros(size(nets, 1), 1);
    for i=1:size(nets, 1)
        if nets(i) < -45
            outs(i) = 0;
        elseif nets(i) > 45
            outs(i) = 1;
        else
            outs(i) = 1/1+exp(-nets(i));
        end
    end
end
4

2 回答 2

2

根据我们在评论中确定的内容,我唯一想到的就是所有食谱一起写在这个伟大的 NN 档案中:

ftp://ftp.sas.com/pub/neural/FAQ2.html#questions

您可以尝试的第一件事是:

1)如何避免逻辑函数溢出?可能这就是问题所在 - 很多时候我已经实现了 NN,问题在于这样的溢出。

2)类别应该如何编码?

更一般的:

3)病态如何影响神经网络训练?

4)帮助!我的NN不会学习!我应该怎么办?

于 2013-08-05T11:40:02.837 回答
1

经过讨论后发现问题出在 sigmoid 函数中:

function outs = sigmoid(nets)
%...
            outs(i) = 1/1+exp(-nets(i)); % parenthesis missing!!!!!!
%...
end

它应该是:

function outs = sigmoid(nets)
%...
            outs(i) = 1/(1+exp(-nets(i)));
%...
end

缺少括号导致有时sigmoid输出大于1。这使得梯度计算不正确(因为它不是这个函数的梯度)。这导致梯度为负。这导致输出层的增量大部分时间都在错误的方向上。修复后(正确维护错误变量后 - 这似乎在您的代码中丢失)一切似乎都工作正常。


除此之外,这段代码还有另外两个主要问题:

1)没有偏见。如果没有偏差,每个神经元只能代表一条穿过原点的线。如果数据被规范化(即值在 0 和 1 之间),一些配置是不可分割的。

2)缺乏对高梯度值的防范(我之前的回答中的第 1 点)。

于 2013-08-07T12:19:51.810 回答