Pensavo di dare a tutti un aggiornamento delle possibili soluzioni che potrebbero funzionare. Come accennato in precedenza, i dati sono complicati dalle frequenze sinusoidali variabili, quindi alcuni metodi potrebbero non funzionare a causa di ciò. I metodi elencati di seguito possono essere buoni a seconda dei dati e delle frequenze coinvolte.
Prima di tutto, suppongo che i dati ha la forma:
y = average + b*e^-(c*x)
Nel mio caso, la media è 290 quindi abbiamo:
y = 290 + b*e^-(c*x)
Detto questo, cerchiamo di tuffarsi i diversi metodi che ho provato:
findpeaks() Metodo
Questo è il metodo suggerito da Alexander Büse.È un metodo abbastanza buono per la maggior parte dei dati, ma per i miei dati, dato che ci sono più frequenze sinusoidali, si ottengono i picchi errati. Le x rosse mostrano le vette.
% Find Peaks Method
[max_num,max_ind] = findpeaks(y(ind));
plot(max_ind,max_num,'x','Color','r'); hold on;
x1 = max_ind;
y1 = log(max_num-290);
coeffs = polyfit(x1,y1,1)
b = exp(coeffs(2));
c = coeffs(1);
RANSAC
RANSAC è buono se si dispone di maggior parte dei dati in corrispondenza dei picchi. Lo vedi nel mio, a causa delle frequenze multiple, più picchi esistono vicino alla cima. Tuttavia, il problema con i miei dati è che non tutti i set di dati sono così. Quindi, occasionalmente ha funzionato.
% RANSAC Method
ind = (y > avg);
x1 = x(ind);
y1 = log(y(ind) - avg);
iterNum = 300;
thDist = 0.5;
thInlrRatio = .1;
[t,r] = ransac([x1;y1'],iterNum,thDist,thInlrRatio);
k1 = -tan(t);
b1 = r/cos(t);
% plot(x1,k1*x1+b1,'r'); hold on;
b = exp(b1);
c = k1;
Metodo Lsqlin
Questo metodo è quello utilizzato here. Usa Lsqlin per vincolare il sistema. Tuttavia, sembra ignorare i dati nel mezzo. A seconda del set di dati, questo potrebbe funzionare molto bene come ha fatto per la persona nel post originale.
% Lsqlin Method
avg = 290;
ind = (y > avg);
x1 = x(ind);
y1 = log(y(ind) - avg);
A = [ones(numel(x1),1),x1(:)]*1.00;
coeffs = lsqlin(A,y1(:),-A,-y1(:),[],[],[],[],[],optimset('algorithm','active-set','display','off'));
b = exp(coeffs(2));
c = coeffs(1);
Trova Picchi nella Periodo
questo è il metodo che ho citato nel mio post dove ho il picco in ogni regione,. Questo metodo funziona abbastanza bene e da questo ho capito che i miei dati potrebbero non avere una perfetta corrispondenza esponenziale. Vediamo che non è in grado di adattarsi ai grandi picchi all'inizio. Sono riuscito a migliorarlo un po 'usando solo i primi 150 punti dati e ignorando i punti dati a stato stazionario. Qui ho trovato il picco ogni 25 punti dati.
% Incremental Method 2 Unknowns
x1 = [];
y1 = [];
max_num=[];
max_ind=[];
incr = 25;
for i=1:floor(size(y,1)/incr)
[max_num(end+1),max_ind(end+1)] = max(y(1+incr*(i-1):incr*i));
max_ind(end) = max_ind(end) + incr*(i-1);
if max_num(end) > avg
x1(end+1) = max_ind(end);
y1(end+1) = log(max_num(end)-290);
end
end
plot(max_ind,max_num,'x','Color','r'); hold on;
coeffs = polyfit(x1,y1,1)
b = exp(coeffs(2));
c = coeffs(1);
utilizzando tutti 500 punti dati:
utilizzando i primi 150 punti dati:
Trova Picchi in epoca con b vincolata
Dal momento che voglio che iniziare al primo picco, ho limitato il valore b. So che il sistema è y=290+b*e^-c*x
e lo vincolo in modo tale che b=y(1)-290
. In tal modo, ho solo bisogno di risolvere per c dove c=(log(y-290)-logb)/x
. Posso quindi prendere la media o mediana di c. Questo metodo è abbastanza buono, non si adatta anche al valore vicino alla fine, ma non è un grosso problema dato che il cambiamento è minimo.
% Incremental Method 1 Unknown (b is constrained y(1)-290 = b)
b = y(1) - 290;
c = [];
max_num=[];
max_ind=[];
incr = 25;
for i=1:floor(size(y,1)/incr)
[max_num(end+1),max_ind(end+1)] = max(y(1+incr*(i-1):incr*i));
max_ind(end) = max_ind(end) + incr*(i-1);
if max_num(end) > avg
c(end+1) = (log(max_num(end)-290)-log(b))/max_ind(end);
end
end
c = mean(c); % Or median(c) works just as good
Qui prendo il picco per ogni 25 punti di dati e poi prendere la media dei c
Qui prendo il picco per ogni 25 punti di dati e poi prendere il mediano di c
Qui prendo il picco per ogni 10 punti di dati e poi prendere la media dei c
Grazie Alessandro. Quindi la cosa complicata con questi dati è che non è solo una frequenza sinusoidale, quindi l'uso di findpeaks finisce per ottenere picchi dell'onda che in realtà non sono il massimo nella regione. Ho aggiornato il mio post originale con il segnale effettivo con i punti collegati. Devo ancora provare a montarlo con gli strumenti di adattamento della curva (non ce l'ho sul mio computer) ma farò un tentativo quando sono a scuola. –