【问题标题】:Application of Neural Network in MATLAB神经网络在MATLAB中的应用
【发布时间】:2013-10-06 10:18:06
【问题描述】:

几天前我问了一个问题,但我想它有点太复杂了,我不希望得到任何答案。

我的问题是我需要使用 ANN 进行分类。我读过更好的成本函数(或某些书籍指定的损失函数)是交叉熵,即J(w) = -1/m * sum_i( yi*ln(hw(xi)) + (1-yi)*ln(1 - hw(xi)) )i 表示编号。来自训练矩阵X的数据。我试图在 MATLAB 中应用它,但我发现它真的很难。有几件事我不知道:

  • 在给定所有训练数据的情况下,我是否应该对每个输出求和(i = 1,... N,其中 N 是训练的输入数)
  • 梯度计算是否正确
  • 是正确计算的数值梯度 (gradAapprox)。

我有以下 MATLAB 代码。我意识到我可能会要求一些琐碎的事情,但无论如何我希望有人能给我一些如何找到问题的线索。我怀疑问题在于计算梯度。

非常感谢。

主脚本:

close all
clear all

L = @(x) (1 + exp(-x)).^(-1);
NN = @(x,theta) theta{2}*[ones(1,size(x,1));L(theta{1}*[ones(size(x,1),1) x]')];

% theta = [10 -30 -30];
x = [0 0; 0 1; 1 0; 1 1];
y = [0.9 0.1 0.1 0.1]';

theta0 = 2*rand(9,1)-1;
options = optimset('gradObj','on','Display','iter');
thetaVec = fminunc(@costFunction,theta0,options,x,y);
theta = cell(2,1);
theta{1} = reshape(thetaVec(1:6),[2 3]);
theta{2} = reshape(thetaVec(7:9),[1 3]);

NN(x,theta)'

成本函数:

function [jVal,gradVal,gradApprox] = costFunction(thetaVec,x,y)
persistent index;

%     1 x x
%     1 x x
%     1 x x
% x = 1 x x
%     1 x x
%     1 x x
%     1 x x

m = size(x,1);

if isempty(index) || index > size(x,1)
    index = 1;
end

L = @(x) (1 + exp(-x)).^(-1);
NN = @(x,theta) theta{2}*[ones(1,size(x,1));L(theta{1}*[ones(size(x,1),1) x]')];

theta = cell(2,1);
theta{1} = reshape(thetaVec(1:6),[2 3]);
theta{2} = reshape(thetaVec(7:9),[1 3]);
Dew = cell(2,1);
DewApprox = cell(2,1);

% Forward propagation
a0 = x(index,:)';
z1 = theta{1}*[1;a0];
a1 = L(z1);
z2 = theta{2}*[1;a1];
a2 = L(z2);

% Back propagation
d2 = 1/m*(a2 - y(index))*L(z2)*(1-L(z2));
Dew{2} = [1;a1]*d2;
d1 = [1;a1].*(1 - [1;a1]).*theta{2}'*d2;
Dew{1} = [1;a0]*d1(2:end)';

% NNRes = NN(x,theta)';
% jVal = -1/m*sum(NNRes-y)*NNRes*(1-NNRes);
jVal = -1/m*(a2 - y(index))*a2*(1-a2);
gradVal = [Dew{1}(:);Dew{2}(:)];

gradApprox = CalcGradApprox(0.0001);

index = index + 1;

function output = CalcGradApprox(epsilon)
    output = zeros(size(gradVal));
    for n=1:length(thetaVec)
        thetaVecMin = thetaVec;
        thetaVecMax = thetaVec;
        thetaVecMin(n) = thetaVec(n) - epsilon;
        thetaVecMax(n) = thetaVec(n) + epsilon;

        thetaMin = cell(2,1);
        thetaMax = cell(2,1);
        thetaMin{1} = reshape(thetaVecMin(1:6),[2 3]);
        thetaMin{2} = reshape(thetaVecMin(7:9),[1 3]);
        thetaMax{1} = reshape(thetaVecMax(1:6),[2 3]);
        thetaMax{2} = reshape(thetaVecMax(7:9),[1 3]);

        a2min = NN(x(index,:),thetaMin)';
        a2max = NN(x(index,:),thetaMax)';
        jValMin = -1/m*(a2min-y(index))*a2min*(1-a2min);
        jValMax = -1/m*(a2max-y(index))*a2max*(1-a2max);
        output(n) = (jValMax - jValMin)/2/epsilon;
    end
end
end

编辑: 下面我为可能感兴趣的人展示我的 costFunction 的正确版本。

function [jVal,gradVal,gradApprox] = costFunction(thetaVec,x,y)
    m = size(x,1);

    L = @(x) (1 + exp(-x)).^(-1);
    NN = @(x,theta) L(theta{2}*[ones(1,size(x,1));L(theta{1}*[ones(size(x,1),1) x]')]);

    theta = cell(2,1);
    theta{1} = reshape(thetaVec(1:6),[2 3]);
    theta{2} = reshape(thetaVec(7:9),[1 3]);
    Delta = cell(2,1);
    Delta{1} = zeros(size(theta{1}));
    Delta{2} = zeros(size(theta{2}));
    D = cell(2,1);
    D{1} = zeros(size(theta{1}));
    D{2} = zeros(size(theta{2}));
    jVal = 0;

    for in = 1:size(x,1)
        % Forward propagation
        a1 = [1;x(in,:)']; % added bias to a0
        z2 = theta{1}*a1;
        a2 = [1;L(z2)]; % added bias to a1
        z3 = theta{2}*a2;
        a3 = L(z3);
        % Back propagation
        d3 = a3 - y(in);
        d2 = theta{2}'*d3.*a2.*(1 - a2);
        Delta{2} = Delta{2} + d3*a2';
        Delta{1} = Delta{1} + d2(2:end)*a1';
        jVal = jVal + sum(  y(in)*log(a3) + (1-y(in))*log(1-a3)  );
    end
    D{1} = 1/m*Delta{1};
    D{2} = 1/m*Delta{2};

    jVal = -1/m*jVal;
    gradVal = [D{1}(:);D{2}(:)];
    gradApprox = CalcGradApprox(x(in,:),0.0001);



    % Nested function to calculate gradApprox
    function output = CalcGradApprox(x,epsilon)
        output = zeros(size(thetaVec));
        for n=1:length(thetaVec)
            thetaVecMin = thetaVec;
            thetaVecMax = thetaVec;
            thetaVecMin(n) = thetaVec(n) - epsilon;
            thetaVecMax(n) = thetaVec(n) + epsilon;

            thetaMin = cell(2,1);
            thetaMax = cell(2,1);
            thetaMin{1} = reshape(thetaVecMin(1:6),[2 3]);
            thetaMin{2} = reshape(thetaVecMin(7:9),[1 3]);
            thetaMax{1} = reshape(thetaVecMax(1:6),[2 3]);
            thetaMax{2} = reshape(thetaVecMax(7:9),[1 3]);

            a3min = NN(x,thetaMin)';
            a3max = NN(x,thetaMax)';
            jValMin = 0;
            jValMax = 0;
            for inn=1:size(x,1)
                jValMin = jValMin + sum(  y(inn)*log(a3min) + (1-y(inn))*log(1-a3min)  );
                jValMax = jValMax + sum(  y(inn)*log(a3max) + (1-y(inn))*log(1-a3max)  );
            end
            jValMin = 1/m*jValMin;
            jValMax = 1/m*jValMax;
            output(n) = (jValMax - jValMin)/2/epsilon;
        end
    end
end

【问题讨论】:

    标签: matlab neural-network


    【解决方案1】:

    我只是快速浏览了您的代码。这里有一些提示。

    第一季度

    在给定所有训练数据的情况下,我是否应该对每个输出求和(i = 1,... N,其中 N 是训练的输入数)

    如果您谈论的是成本函数,通常按训练示例的数量求和并归一化以提供比较。

    我无法从代码中判断您是否有一个会改变答案的矢量化实现。请注意,sum 函数一次只会对一个维度求和 - 这意味着如果您有一个 (M x N) 数组,sum 将产生一个 1 x N 数组。

    成本函数应该有一个标量输出。

    第二季度

    梯度计算是否正确

    梯度计算不正确 - 特别是增量看起来错误。尝试关注Andrew Ng's notes [PDF] 他们非常好。

    第三季度

    是正确计算的数值梯度(gradAapprox)。

    这条线看起来有点可疑。这更有意义吗?

    output(n) = (jValMax - jValMin)/(2*epsilon);
    

    编辑:我实际上无法使您的渐变近似值出现正面或反面。您应该只使用前向传播和参数中的小调整来计算梯度。祝你好运!

    【讨论】:

    • 卢克你好。首先。谢谢你的回答。我会检查你提供的笔记。目前,我只会对 Q3 评论说,您的表达式与我在 MATLAB 中的表达式相同,但在视觉上您的表达式看起来更清晰。干杯!
    • 嘿卢克,谢谢你的笔记。现在一切正常,分析和数值计算的梯度非常相似,这意味着模型训练正确:) 祝你好运,Ziko
    猜你喜欢
    • 2015-12-03
    • 2011-08-23
    • 2011-03-26
    • 2014-01-15
    • 2015-08-13
    • 2011-03-08
    • 2015-06-29
    • 2018-12-30
    相关资源
    最近更新 更多