Pomyślałem, że dam wszystkim aktualizację potencjalnych rozwiązań, które mogą działać. Jak wspomniano wcześniej, dane są komplikowane przez zmienne częstotliwości sinusoidalne, więc niektóre metody mogą z tego powodu nie działać. Wymienione poniżej metody mogą być dobre w zależności od danych i częstotliwości.
Po pierwsze, zakładam, że dane mają postać:
y = average + b*e^-(c*x)
w moim przypadku, średnia wynosi 290, więc mamy:
y = 290 + b*e^-(c*x)
Z tym mówi, niech zanurzyć różne metody, które próbowałem:
findpeaks() Metoda
Jest to metoda zalecana przez Alexandra Büse.Jest to całkiem dobra metoda dla większości danych, ale dla moich danych, ponieważ istnieje wiele częstotliwości sinusoidalnych, otrzymuje błędne wartości szczytowe. Czerwone X pokazują szczyty.
% 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 jest dobre, jeśli masz większość danych na szczyty. Widzisz to w moim, ze względu na wiele częstotliwości, więcej szczytów istnieje blisko szczytu. Jednak problem z moimi danymi jest taki, że nie wszystkie zestawy danych są takie. Dlatego od czasu do czasu zadziałało.
% 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;
Metoda Lsqlin
Ta metoda jest jeden używany here. Używa Lsqlin do ograniczenia systemu. Jednak wydaje się, że ignoruje dane w środku. W zależności od zestawu danych może to działać naprawdę dobrze, jak w przypadku osoby w oryginalnym wpisie.
% 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);
Znajdź Szczyty w Okresie
Jest to metoda wspominałem w moim poście gdzie mogę dostać się na szczyt w każdym regionie. Ta metoda działa całkiem dobrze iz tego powodu zdałem sobie sprawę, że moje dane mogą nie mieć doskonałego dopasowania wykładniczego. Widzimy, że nie jest on w stanie dopasować dużych szczytów na początku. Udało mi się to nieco poprawić, wykorzystując tylko pierwsze 150 punktów danych i ignorując punkty danych stanu ustalonego. Tutaj znalazłem szczyt co 25 punktów danych.
% 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);
wykorzystując wszystkie 500 punktów danych:
Korzystanie pierwszych 150 punktów danych:
Znajdź Szczyty w Okresie Z b Ograniczone
ponieważ chcę go zacznij od pierwszego szczytu, ograniczyłem wartość b. Wiem, że system jest y=290+b*e^-c*x
i ograniczam go tak, że b=y(1)-290
. W ten sposób, po prostu muszę rozwiązać c, gdzie c=(log(y-290)-logb)/x
. Mogę wtedy wziąć średnią lub medianę c. Ta metoda jest również dobra, nie pasuje również do wartości zbliżonej do końca, ale nie jest to tak duża oferta, ponieważ zmiana jest minimalna.
% 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
Oto biorę szczyt na 25 punktów danych, a następnie podjąć średnio ok
Oto biorę szczyt na 25 punktów danych, a następnie podjąć medianę c
Oto biorę szczyt na każde 10 punktów danych, a następnie podjąć średnio ok
Dzięki Alexander. Trudność z tymi danymi polega na tym, że nie jest to tylko jedna sinusoidalna częstotliwość, więc użycie findpeaks kończy się uzyskiwaniem szczytów fali, które w rzeczywistości nie są maksymalne w regionie. Zaktualizowałem mój pierwotny post z faktycznym sygnałem z połączonymi punktami. Nie próbowałem jeszcze dopasować go do przybornika dopasowującego krzywa (nie mam go na moim komputerze), ale spróbuję, gdy będę w szkole. –