matlab error particleswarm目标函数必须返回标量值

时间:2018-04-24 17:54:14

标签: matlab

我正在尝试使用MATLAB2014b中的PARTICLESWARM函数来解决优化问题。借助于开源ECG工具箱,1.0版,2006年11月根据GNU通用公共许可证发布。

该代码的主要目的是找到心电图模型的最佳参数,以达到最小的模型误差。

我使用PSO作为优化器来找到这些最佳参数。出现错误:

Error using particleswarm>makeState (line 683)
Objective function must return scalar values.
Error in particleswarm>pswcore (line 164)
state = makeState(nvars,lbMatrix,ubMatrix,objFcn,options);
Error in particleswarm (line 146)
[x,fval,exitFlag,output] = pswcore(objFcn,nvars,lbRow,ubRow,output,options);
Error in ECGOptimizeModel (line 16)
param = particleswarm(@(InitParams) ECGModelError(InitParams,x,meanphase,0),length(InitParams),InitParams-2,InitParams+2,options)
Error in MY_ECGBeatFitterAuto (line 139)
[params model er] = ECGOptimizeModel(y, indx, meanphase);cannot continue

我的职能在这里:

function b = BaseLine1(x,L,approach)
%
% b = BaseLine1(x,L,approach),
% Baseline wander extraction from biomedical recordings, using a single 
% stage of median or moving average filtering.
%
% inputs:
% x: vector or matrix of noisy data (channels x samples)
% L: averaging window length (in samples)
% approach:
%   'md': median filtering
%   'mn': moving average
%
% output:
% b: vector or matrix of baseline wanders (channels x samples)
%
%
% Open Source ECG Toolbox, version 1.0, November 2006
% Released under the GNU General Public License
% Copyright (C) 2006  Reza Sameni
% Sharif University of Technology, Tehran, Iran -- GIPSA-Lab, INPG, Grenoble, France
% reza.sameni@gmail.com

% This program is free software; you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation; either version 2 of the License, or (at your
% option) any later version.
% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details.

N = size(x,2);
b = zeros(size(x));
flen = floor(L/2);

if (strcmp(approach,'mn'))      % moving average filter
    for j = 1:N,
        index = max(j-flen,1):min(j+flen,N);
        b(:,j) = mean(x(:,index),2);
    end
elseif (strcmp(approach,'md'))  % median filter
    for j = 1:N,
        index = max(j-flen,1):min(j+flen,N);
        b(:,j) = median(x(:,index),2);
    end
end
function y = LPFilter(x,fc)
%
% y = LPFilter(x,fc),
% Second order zero-phase Lowpass filter
%
% inputs:
% x: vector or matrix of input data (channels x samples)
% fc: -3dB cut-off frequency normalized by the sampling frequency
%
% output:
% y: vector or matrix of filtered data (channels x samples)
%
%
% Open Source ECG Toolbox, version 1.0, November 2006
% Released under the GNU General Public License
% Copyright (C) 2006  Reza Sameni
% Sharif University of Technology, Tehran, Iran -- GIPSA-Lab, INPG, Grenoble, France
% reza.sameni@gmail.com

% This program is free software; you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation; either version 2 of the License, or (at your
% option) any later version.
% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details.


k = .7;     % cut-off value
alpha = (1-k*cos(2*pi*fc)-sqrt(2*k*(1-cos(2*pi*fc))-k^2*sin(2*pi*fc)^2))/(1-k);
y = zeros(size(x));
for i = 1:size(x,1)
    y(i,:) = filtfilt(1-alpha,[1 -alpha],x(i,:));
end
function [ECGmean,ECGsd,meanPhase] = MeanECGExtraction(x,phase,bins,flag)
%
% [ECGmean,ECGsd,meanPhase] = MeanECGExtraction(x,phase,bins,flag)
% Calculation of the mean and SD of ECG waveforms in different beats
%
% inputs:
% x: input ECG signal
% phase: ECG phase
% bins: number of desired phase bins
% flag
%     1: aligns the baseline on zero, by using the mean of the first 10%
%     segment of the calculated mean ECG beat
%     0: no baseline alignment
%
% outputs:
% ECGmean: mean ECG beat
% ECGsd: standard deviation of ECG beats
% meanPhase: the corresponding phase for one ECG beat
%
%
% Open Source ECG Toolbox, version 2.0, March 2008
% Released under the GNU General Public License
% Copyright (C) 2008  Reza Sameni
% Sharif University of Technology, Tehran, Iran -- LIS-INPG, Grenoble, France
% reza.sameni@gmail.com

% This program is free software; you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation; either version 2 of the License, or (at your
% option) any later version.
% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details.

meanPhase = zeros(1,bins);
ECGmean = zeros(1,bins);
ECGsd = zeros(1,bins);

I = find( phase>=(pi-pi/bins)  | phase<(-pi+pi/bins) );
if(~isempty(I))
    meanPhase(1) = -pi;
    ECGmean(1) = mean(x(I));
    ECGsd(1) = std(x(I));
else
    meanPhase(1) = 0;
    ECGmean(1) =0;
    ECGsd(1) = -1;
end
for i = 1 : bins-1;
    I = find( phase >= 2*pi*(i-0.5)/bins-pi & phase < 2*pi*(i+0.5)/bins-pi );
    if(~isempty(I))
        meanPhase(i + 1) = mean(phase(I));
        ECGmean(i + 1) = mean(x(I));
        ECGsd(i + 1) = std(x(I));
    else
        meanPhase(i + 1) = 0;
        ECGmean(i + 1) = 0;
        ECGsd(i + 1) = -1;
    end
end
K = find(ECGsd==-1);
for i = 1:length(K),
    switch K(i)
        case 1
            meanPhase(K(i)) = -pi;
            ECGmean(K(i)) = ECGmean(K(i)+1);
            ECGsd(K(i)) = ECGsd(K(i)+1);
        case bins
            meanPhase(K(i)) = pi;
            ECGmean(K(i)) = ECGmean(K(i)-1);
            ECGsd(K(i)) = ECGsd(K(i)-1);
        otherwise
            meanPhase(K(i)) = mean([meanPhase(K(i)-1),meanPhase(K(i)+1)]);
            ECGmean(K(i)) = mean([ECGmean(K(i)-1),ECGmean(K(i)+1)]);
            ECGsd(K(i)) = mean([ECGsd(K(i)-1),ECGsd(K(i)+1)]);
    end
end

if(flag==1)
    ECGmean = ECGmean - mean(ECGmean(1:ceil(length(ECGmean)/10)));
end
function phase = PhaseShifting(phasein,teta)
%
% phase = PhaseShifting(phasein,teta),
% Phase shifter.
%
% inputs:
% phasein: calculated ECG phase
% teta: desired phase shift. teta>0 and teta<0 corresponds with phase leads
% and phase lags, respectively.
%
% output:
% phase: the shifted phase.

phase = phasein + teta;
phase = mod(phase + pi, 2*pi) - pi;
function [phase phasepos] = PhaseCalculation(peaks)

phasepos = zeros(1,length(peaks));

I = find(peaks);
for i = 1:length(I)-1;
    m = I(i+1) - I(i);
    phasepos(I(i)+1:I(i+1)) = 2*pi/m : 2*pi/m : 2*pi;
end
m = I(2) - I(1);
L = length(phasepos(1:I(1)));
phasepos(1:I(1)) = 2*pi-(L-1)*2*pi/m:2*pi/m:2*pi;

m = I(end) - I(end-1);
L = length(phasepos(I(end)+1:end));
phasepos(I(end)+1:end) = 2*pi/m:2*pi/m:L*2*pi/m;

phasepos = mod(phasepos,2*pi);

phase = phasepos; 
I = find(phasepos>pi);
phase(I) = phasepos(I) - 2*pi;
function E = ECGModelError(X,ECGmn,Phasemn,flag);
%
% Synthetic ECG model error
%
% Open Source ECG Toolbox, version 1.0, November 2006
% Released under the GNU General Public License
% Copyright (C) 2006  Reza Sameni
% Sharif University of Technology, Tehran, Iran -- LIS-INPG, Grenoble, France
% reza.sameni@gmail.com

% This program is free software; you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the
% Free Software Foundation; either version 2 of the License, or (at your
% option) any later version.
% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
% Public License for more details. You should have received a copy of the
% GNU General Public License along with this program; if not, write to the
% Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
% MA  02110-1301, USA.

L = (length(X)/3);

alphai = X(1:L);
bi = X(L+1:2*L);
tetai = X(2*L+1:3*L);

Z = zeros(size(ECGmn));
for j = 1:length(alphai),
    dtetai = rem(Phasemn - tetai(j) + pi,2*pi)-pi;
    Z = Z + alphai(j) .* exp(-dtetai .^2 ./ (2*bi(j) .^ 2));
end

if(flag==0)
    E = (Z-ECGmn);
elseif(flag==1)
    E = (Z);
end
function [params model er] = ECGOptimizeModel(x, indexes, meanphase)
tetai = meanphase(indexes);
alphai = 1*x(indexes); %1.2
bi = .01*ones(size(alphai));%0.04

% options = optimset('TolX',1e-4,'TolFun',1e-4,'MaxIter',100);
%%%options = optimset('TolX',1e-4,'TolFun',1e-4,'MaxIter',50,'Display','off');
InitParams = [alphai bi tetai];

 %params = nlinfit(meanphase,x,@ECGModel,InitParams,options);
%%%params = lsqnonlin(@(InitParams) ECGModelError(InitParams,x,meanphase,0),InitParams,InitParams-2,InitParams+2,options);

rng default
options = optimoptions('particleswarm','SwarmSize',50,'HybridFcn',@fminsearch);
%fun =@ECGModelError(InitParams,x,meanphase,0);
param = particleswarm(@(InitParams) ECGModelError(InitParams,x,meanphase,0),length(InitParams),InitParams-2,InitParams+2,options)

% Model0 = ECGModelError(InitParams,x,meanphase,1);
model = ECGModelError(params,x,meanphase,1);
er = 100*mean((x-model).^2)/mean(x.^2);
clc
clear all
close all;
**%  THE MAIN CODE**
load('SampleECG2.mat'); data = data(1:15000,3)';

fs = 1000;
t = [0:length(data)-1]/fs;

f = 1;                                          % approximate R-peak frequency

bsline = LPFilter(data,.7/fs);                  % baseline wander removal (may be replaced by other approaches)
x = data - bsline +.5*randn(size(data));
peaks = PeakDetection(x,f/fs);                  % peak detection
%peaks = PeakDetection2(x,fs); 
[phase phasepos] = PhaseCalculation(peaks);     % phase calculation

%% peak detection (Pan-Tompkins)
%peaks2 = PeakDetection2(x,fs);      % peak detection (Pan-Tompkins)
%figure;
%plot(t,x,'b');
%hold on
%plot(t,peaks2.*x,'go');
%xlabel('time (sec.)');
%ylabel('ECG Peaks(Pan-Tompkins)')
%%
teta = 0;                                       % desired phase shift
pphase = PhaseShifting(phase,teta);             % phase shifting

bins = fs/2;                                     % number of phase bins
[ECGmean,ECGsd,meanphase] = MeanECGExtraction(x,pphase,bins,1);


%% ECGBeatFitterAuto(ECGmean,meanphase)
% inputs:
% ECGmean:      the input ECG beat
% meanphase:    the phase signal of the ECG beat
% approach:     'fixed number' or 'min error'
% stopth:       stopping threshold error percentage
% divisions:    number of divisions for random point approach
% maxit:        maximum number of iterations for randomized methods
% energyth:     the energy threshold used for detecting peaks (default: 0.001)
% wlen:         peak search window length (default: 0.01*SignalLength)

% beat length
N = length(ECGmean);

% idle segment at the beginning of the beat
L0 = ceil(N/10);

stopth = .001; % percentage of error
num = 10;
maxitr = 10;
approach = 'min error'; % fixed number/min error
energyth = 0.0001;
th=energyth;
wlen = 3;

%% preprocessing
base = median(ECGmean(1:L0));
x = ECGmean - base;
y = BaseLine1(x,5,'md');%LPFilter(d,25/N);
% y = wden(x,'rigrsure','s','mln',6,'coif5');
y = LPFilter(y,45/N);

% % % figure;
% % % hold on;
% % % plot(x);
% % % plot(y,'r');
% % % grid

%% approach,'min error'
if(strcmp(approach,'min error'))

 % zero crossing detection
    zc = [0 y(1:end-1).*y(2:end)];
    I = find(zc<=0);
    E = sum(x.^2);
    II = [];
    m0 = find(I>L0,1);
    m = m0;
    for i = m0:length(I),
        ind = I(m):I(i);
        if(sum(x(ind).^2)>th*E)
            if(isempty(II))
                II = [I(m) I(i)];
            else
                II = [II I(i)];
            end
            m = m + 1;
        end
    end

    %//////////////////////////////////////////////////////////////////////////
    % local peak detection

    pk = zeros(1,N);
    for i = L0:N-L0,
        ind = max(i-wlen,1):min(i+wlen,N);
        if(y(i)==max(y(ind)) && y(i)>0 && std(y(ind))~=0) % local max with positive amplitudes
            pk(i) = 1;
        elseif(y(i)==min(y(ind)) && y(i)<0 && std(y(ind))~=0) % local min with negative amplitudes
            pk(i) = 1;
        end
    end
    J = find(pk);

    E = sum(y.^2);
    JJ = [];
    m0 = find(J>L0,1);
    m = m0;
    for i = m0:length(J),
        ind = J(m):J(i);
        if(sum(y(ind).^2)>th*E)
            if(isempty(JJ))
                JJ = [J(m) J(i)];
            else
                JJ = [JJ J(i)];
            end
            m = m + 1;
        end
    end

    %//////////////////////////////////////////////////////////////////////////
    % merge the results
    K = sort([I J]);
    KK = sort([II JJ]);

    % uniform points
    UU = L0:round(N/num):N-L0;

    %plot(zc),hold on,plot(JJ,zc(JJ),'m*')

    %% start optimizing
    done = logical(0);
    % peaks alone
    if(~done)
        indx = JJ;
        [params model er] = ECGOptimizeModel(y, indx, meanphase);
        indexes = indx;
        if(er<stopth)
            method = 0;
            done = 1;
        end
    end

if(~done)
        disp('Info: The specified requirements have not been met with fixed error model; continuing with random point approach.');
        approach = 'fixed number';
    end
elseif(strcmp(approach,'fixed number'))

%% uniform points
    UU = L0:round((N-2*L0)/num):N-L0;
    er = 100;
    for i = 1:maxitr,
        indx = UU + round((rand(size(UU))-.5)*N/10);
        indx = sort(indx);
        indx = indx(indx>=1);
        indx = indx(indx<=N);
        [params_ model_ er_] = ECGOptimizeModel(y, indx, meanphase);
        if(er_<er)
            indexes = indx;
            params = params_;
            model = model_;
            er = er_;
            if(er<stopth)
                method = 13;
                done = 1;
                break;
            end
        end
    end
end

disp(['Final model fitting error percentage: ',num2str(er)]);

% plot the results
n = 1:length(x);
figure;
plot(n,x);
hold on;
plot(n,y,'r');
plot(n,model,'k','LineWidth',2);
plot(n(indexes),x(indexes),'ro','linewidth',2);
grid

% % % grid
 disp(['Error = ',num2str(er),'%']);

%% display the optimal parameters
L = length(params)/3;
ai = params(1:L);
bi = params(L+1:2*L);
tetai = params(2*L+1:3*L);

figure;
plot(t,data*6/max(data),'b');
hold on
plot(t,peaks*2,'ro');
plot(t,phase,'c--','linewidth',1);
plot(t,pphase,'g','linewidth',1);
grid;
xlabel('time (sec.)');
legend('Scaled ECG','ECG Peaks','phase','shifted phase');

figure;
errorbar(meanphase,ECGmean,ECGsd/2);
hold on;
plot(meanphase,ECGmean,'r');
legend('SD Bar','Mean ECG');
xlabel('phase (rads.)');
grid


 % % % plot(d,'g');
% % % plot(dd,'m');
% % % plot(ddd,'k');
% % % plot(n(I),y(I),'ro','linewidth',3);
% % % plot(n(II),y(II),'go','linewidth',3);
% % % plot(n(J),y(J),'ro','linewidth',3);
% % % plot(n(JJ),y(JJ),'go','linewidth',3);
% % % plot(n(K),y(K),'ro','linewidth',1);
% % % plot(n(KK),y(KK),'go','linewidth',3);
% % % plot(n(UU),y(UU),'go','linewidth',3);
% % % grid

数据:https://drive.google.com/open?id=1OieiPKJemlAqPXkhje9s0d5b9uCy0etb

0 个答案:

没有答案