Ik zoek een makkelijke maar vooral robuste manier om de lokale maxima/minima te vinden van een gesampelde functie. In dit geval is het een sinus-achtige golf.
Input: array van floats met integer index (std::vector<float>)
Output: array van integer indices voor alle lokale maxima en minima
Wat ik nu doe:
Het probleem daarmee is dat er soms iets van ruis in de data zit, en er dan hele kleine lokale extremen worden gevonden. Bijvoorbeeld hier:
Maar soms is dat over iets meer samples verspreid: het is niet altijd alleen de volgende die fout gaat. Een ander probleem is als het maximum gelijk is, dan zou hij het midden moeten proberen te vinden:
Nu kan ik wel de uiteindelijke lijst weer doorlopen om dit soort dingen op te sporen en dan samen te voegen, maar het wordt allemaal een beetje ingewikkeld en ad-hoc. Dat moet toch makkelijker kunnen? Hebben jullie ideeen?
Input: array van floats met integer index (std::vector<float>)
Output: array van integer indices voor alle lokale maxima en minima
Wat ik nu doe:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| void find_peaks(const std::vector<double>& ys, std::vector<int>& mins, std::vector<int>& maxs) { int last_dir = 0; for (int i=1; i<ys.size(); ++i) { int dir; if (ys[i] > ys[i-1]) {dir = +1;} else if (ys[i] < ys[i-1]) {dir = -1;} else {dir = last_dir;} if (dir != 0 && dir != last_dir) { if (dir > 0) { mins.push_back(i); } if (dir < 0) { maxs.push_back(i); } } last_dir = dir; } } |
Het probleem daarmee is dat er soms iets van ruis in de data zit, en er dan hele kleine lokale extremen worden gevonden. Bijvoorbeeld hier:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
| -0.969114 -0.976812 -0.987645 -0.993775 -0.995343 -1 -0.999953 // dit stukje gaat mis -1 -0.996959 -0.989308 -0.983179 -0.969398 -0.950962 |
Maar soms is dat over iets meer samples verspreid: het is niet altijd alleen de volgende die fout gaat. Een ander probleem is als het maximum gelijk is, dan zou hij het midden moeten proberen te vinden:
code:
1
2
3
4
5
6
7
8
9
| 0.992729 0.997196 0.997196 1 // dubbel max, gaat mis 1 1 0.998812 0.995675 0.989688 |
Nu kan ik wel de uiteindelijke lijst weer doorlopen om dit soort dingen op te sporen en dan samen te voegen, maar het wordt allemaal een beetje ingewikkeld en ad-hoc. Dat moet toch makkelijker kunnen? Hebben jullie ideeen?

