Error only triggers when I don't use parfor?

扶醉桌前 提交于 2019-12-12 01:26:57

问题


In the first Matlab script below when I run it as shown I get no errors what so ever and the code produces the expected results, however when I take out matlabpool open and matlabpool close as well as changing the parfor loop to a for loop, I get the following error:

Running...       ??? Error using ==> mldivide
Matrix is singular to working precision.
Error in ==> NSS_betas at 11
    betas = G\data.y2.';
Error in ==> DElambda at 19
        betas(:,ii) = NSS_betas(P1(:,ii),data); end
Error in ==> Individual_Lambdas at 46
    beta{ii} = DElambda(de,dataList, @OF_NSS);

I will happily send CRM_22_12.mat if required.

Why does the error only trigger when I use a regular for loop instead if a parfor loop?

clear all, clc

load Euro_CRM_22_12.mat

matlabpool open 

tic

warnState(1) = warning('error', 'MATLAB:singularMatrix'); 
warnState(2) = warning('error', 'MATLAB:illConditionedMatrix'); 

mats  = 1:50;
mats2 = [2 5 10 30];


% RO: unloop these
de = struct(...
'min', [0;0],...
'max', [50;50],...
'd'  , 2,...
'nP' , 500,...
'nG' , 600,...
'ww' , 0.1,...
'F'  , 0.5,...
'CR' , 0.99,...
'R'  , 0,...
'oneElementfromPm',1);

% RO: initialize beta
beta  = cell(size(rates,1),1);

clc, fprintf('Running...       ');

%for ii = 1:size(rates,1)
parfor ii = 1:size(rates,1)    
% RO: use status indicator for things that take this long
%fprintf('\b\b\b\b\b\b\b%6.2f%%', ii/size(rates,1)*100);

dataList = struct(...
    'yM'   , rates(ii,:),...
    'mats' , mats,...
    'model', @NSS,...
    'mats2', mats2,...
    'y2'   , rates(ii,mats2));

beta{ii} = DElambda(de,dataList, @OF_NSS);

end

toc

matlabpool close

%

function [output] = DElambda(de,data,OF)

% RO: also saves time
 %   warning off; %#ok
warning on verbose;

P1 = zeros(de.d,de.nP);
Pu = zeros(de.d,de.nP);

for ii = 1:de.d
    P1(ii,:) = de.min(ii,1)+(de.max(ii,1)-de.min(ii,1))*rand(de.nP,1); end

P1(:,1:de.d) = diag(de.max);
P1(:,de.d+1:2*de.d) = diag(de.min);

%  RO: pre allocate betas
betas = zeros(size(data.y2,2), de.nP);
for ii = 1:de.nP
    betas(:,ii) = NSS_betas(P1(:,ii),data); end

Params = vertcat(betas,P1);

Fbv = NaN(de.nG,1);

% must pass OF as @OF
F = zeros(de.nP,1);
P = zeros(de.nP,1);

for ii = 1:de.nP
    F(ii) = OF(Params(:,ii)',data);
    P(ii) = pen(P1(:,ii),de,F(ii));
    F(ii) = F(ii)+P(ii);
end

[Fbest indice]  = min(F);
xbest = Params(:,indice);

Col = 1:de.nP;

% RO: pre allocate betasPu
betasPu = zeros(size(data.y2,2), de.nP);

% RO: if Fbest hasn't changed for 25 generations, 
% it's not gonna anymore: break off
count = 0;

for g = 1:de.nG

    P0 = P1;
    rowS = randperm(de.nP).';
    colS = randperm(4).';

    % RO: replace circshift for JIT accelleration
%         RS = circshift(rowS,colS(1));
%         R1 = circshift(rowS,colS(2));
%         R2 = circshift(rowS,colS(3));
%         R3 = circshift(rowS,colS(4));

    RS = rowS([end-colS(1)+1:end 1:end-colS(1)]);        
    R1 = rowS([end-colS(2)+1:end 1:end-colS(2)]);
    R2 = rowS([end-colS(3)+1:end 1:end-colS(3)]);
    R3 = rowS([end-colS(4)+1:end 1:end-colS(4)]);


    % mutate
    Pm = P0(:,R1) + de.F*(P0(:,R2)-P0(:,R3));
    if de.R>0, Pm = Pm+de.r*randn(de.d,de.nP); end

    % crossover
    PmElements = rand(de.d,de.nP)<de.CR;        
    if de.oneElementfromPm
        % RO: JIT...
        %Row = unidrnd(de.d,1,de.nP);
        Row = ceil(de.d .* rand(1,de.nP));

        ExtraPmElements = sparse(Row,Col,1,de.d,de.nP);
        PmElements = PmElements|ExtraPmElements;
    end

    P0_Elements = ~PmElements;
    Pu(:,RS) = P0(:,RS).*P0_Elements+PmElements.*Pm;

    % RO: inline NSS_betas, so that this loop can
    % be compiled by the JIT
    mats = data.mats2.';
    yM   = data.y2.';
    nObs = size(data.y2,2);
    one  = ones(nObs,1);

    % RO: version below is faster
%         for ii = 1:de.nP
%             %betasPu(:,ii) = NSS_betas(Pu(:,ii),data);
%             
%             lambda = Pu(:,ii);
%             G =  [one,...
%                  (1-exp(-mats/lambda(1)))./(mats/lambda(1)),...
%                 ((1-exp(-mats/lambda(1)))./(mats/lambda(1)) - exp(-mats/lambda(1))),...
%                 ((1-exp(-mats/lambda(2)))./(mats/lambda(2)) - exp(-mats/lambda(2)))];
%             
%             betasPu(:,ii) = G\yM;
%             
%         end

    aux  = bsxfun(@rdivide, mats, Pu(:).');
    aux2 = exp(-aux);
    aux3 = (1-aux2)./aux;
    for ii = 1:2:2*de.nP            
%             betasPu(:,(ii+1)/2) =[...
%                one,...
%                aux3(:,ii),...
%                aux3(:,ii) - aux2(:,ii),...
%                aux3(:,ii+1) - aux2(:,ii+1)] \ yM;   
        G=[one, aux3(:,ii), aux3(:,ii) - aux2(:,ii),aux3(:,ii+1) - aux2(:,ii+1)];

        try
        betasPu(:,(ii+1)/2) =G\yM;
        catch ME
         CondPen(1,(ii+1)/2)=0;
        end
     end

    ParamsPu = [betasPu;Pu];
    flag = 0;

    mats  = data.mats;
    yM    = data.yM;

    for ii = 1:de.nP

        % RO: inline OF_NSS.m here for JIT accelleration
        %Ftemp = OF(ParamsPu(:,ii).',data);

        beta = ParamsPu(:,ii).';

        %model = data.model;

        yy = zeros(size(yM));
        for jj = 1:size(beta,3)

            % RO: inline for JIT accelleration
            %y(ii,:) = model(beta(:,:,ii),mats);

            betai = beta(:,:,jj);
            gam1  = mats/betai(5);
            gam2  = mats/betai(6);
            aux1  = 1-exp(-gam1);
            aux2  = 1-exp(-gam2);

            % I have a feeling this is the same as G and therefore 
            % this can be done shorter and quicker...
            % something like yy(jj,:) = sum(G,2)
            yy(jj,:)  = ...
                betai(1) + ...
                betai(2)*(aux1./gam1) + ...
                betai(3)*(aux1./gam1+aux1-1) + ...
                betai(4)*(aux2./gam2+aux2-1);

        end

        yy = yy-yM;

        % RO: this whole loop can be replaced...

        % ObjVal = 0;
        % for i = 1:size(yM,1) %dim
        % ObjVal = ObjVal+dot(aux(i,:)',aux(i,:)');
        % %ObjVal = sum(ObjVal);
        % end
        % ObjVal

        % RO ...by this one-liner
        Ftemp = sum(yy(:).^2);


        % RO: inline penalty here as well
        Ptemp = 0;%pen(Pu(:,ii),de,F(ii));


        Ftemp = Ftemp+Ptemp;%+CondPen(1,ii);

        if Ftemp <= F(ii);
            P1(:,ii) = Pu(:,ii);
            F(ii) = Ftemp;
            if Ftemp < Fbest
                Fbest = Ftemp; xbest = ParamsPu(:,ii); 
                flag = 1; 
                count = 0; 
            end

        else
            P1(:,ii) = P0(:,ii);

        end
    end

    if flag
        Fbv(g) = Fbest; end

    % RO: if Fbest hasn't changed for 25 generatios, break off
    count = count + 1;
    if count > 25, break; end

end

output.Fbest = Fbest; 
output.xbest = xbest; 
output.Fbv = Fbv;    

end


% look to inline penalty later (i.e. incoporate into code
function penVal = pen(~,~,~)%pen(beta,pso,vF,data)
penVal = 0;  
end

%

function [betas r r2] = NSS_betas(lambda,data)

mats = data.mats2.';        
nObs = size(data.y2,2);

G =  [ones(nObs,1),...
     (1-exp(-mats/lambda(1)))./(mats/lambda(1)),...
    ((1-exp(-mats/lambda(1)))./(mats/lambda(1)) - exp(-mats/lambda(1))),...
    ((1-exp(-mats/lambda(2)))./(mats/lambda(2)) - exp(-mats/lambda(2)))];

betas = G\data.y2.';

% RO: output hardly ever needed, while rank() 
% is very time consuming
if nargout > 1 && ~isnan(G)
    r = rank(G);
    r2 = rcond(G);
end


end

回答1:


It's a bit cryptic, but here's what I can tell you for sure.

Error in ==> NSS_betas at 11
    betas = G\data.y2.';
Error in ==> DElambda at 19
        betas(:,ii) = NSS_betas(P1(:,ii),data); end
Error in ==> Individual_Lambdas at 46
    beta{ii} = DElambda(de,dataList, @OF_NSS);

Essentially, this means that the G matrix is singular, and thus doesn't have a solution. That would be this:

G =  [ones(nObs,1),...
     (1-exp(-mats/lambda(1)))./(mats/lambda(1)),...
    ((1-exp(-mats/lambda(1)))./(mats/lambda(1)) - exp(-mats/lambda(1))),...
    ((1-exp(-mats/lambda(2)))./(mats/lambda(2)) - exp(-mats/lambda(2)))];

betas = G\data.y2.';

What I would do to further diagnose this is to set the stop on error flag. There is a few ways to do this, one from the gui, and another via command. Take a look to see if the matrix looks correct. Odds are, something isn't right. Trace back the error, and you'll figure it out.



来源:https://stackoverflow.com/questions/13349145/error-only-triggers-when-i-dont-use-parfor

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!