只有在我不使用parfor时才会触发错误?

时间:2012-11-12 18:13:25

标签: matlab bsxfun

在下面的第一个Matlab脚本中,当我运行它时如图所示,我没有得到任何错误,代码产生了预期的结果,但是当我取出matlabpool open和matlabpool close以及将parfor循环更改为for循环,我得到以下错误:

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);

如果需要,我很乐意发送CRM_22_12.mat。

为什么只有在使用常规for循环时才会触发错误,如果是parfor循环?

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 个答案:

答案 0 :(得分:1)

这有点神秘,但这是我能肯定告诉你的。

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);

基本上,这意味着G矩阵是单数的,因此没有解决方案。就是这样:

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.';

我要做的是进一步诊断这个是设置错误停止标志。有几种方法可以执行此操作,一种来自gui,另一种来自via command。看看矩阵看起来是否正确。可能性有些不对劲。追溯错误,你会发现它。