Hogyan lehet megtalálni a lokális minimumokat az 1D NumPy tömbökben?
Egy függvény szélső helye az az x érték, amelynél a függvény értéke a legnagyobb vagy legkisebb egy adott intervallumban vagy a teljes értelmezési tartományban.
Az f(x)-nek akkor van lokális maximuma x0-ban, ha van olyan környezet, hogy ebben a környezetben bármely x-re f(x) ≥ f(x0). Van f(x) lokális minimuma x0-ban, ha van olyan környezet, hogy ebben a környezetben bármely x-re f(x) ≤ f(x0).
Egy f(x) függvénynek ugyanis több lokális szélsőértéke is lehet. Minden globális szélsőérték egyben lokális is, de fordítva természetesen ez nem igaz.
Ezeket az értékeket gyakran nevezik "csúcsoknak", mert ezek a függvény grafikonján megjelenő "hegyek" és "völgyek" csúcsai.
Ezeknek a pontoknak a gyakorlati alkalmazása alapvető fontosságú, például a képfeldolgozásban és a jelfeldolgozásban, például a földönkívüli üzenetek felderítésében! :)
Ebben a cikkben megnézünk néhány egyszerű módszert arra, hogyan találhatunk mélyedéseket egy numpy tömbben csak a numpy beépített függvényeivel, vagy a scipy könyvtár segítségével.
Az összes minimum egy 1D numpy tömbben.
A helyi minimumok olyan pontok, amelyeket mindkét oldalon nagyobb értékek vesznek körül.
Természetesen sokféleképpen megoldható a feladat, használhatsz tiszta numpy-t, végighaladhatsz az adatokon, vagy használhatod a scipy könyvtárat.
A Githubon találtam egy remek megoldást, Benjamin Schmidt munkáját, ami nagyon jól mutatja a lokális szélsőérték definícióját.
1. módszer: A numpy.where használatával
Kód:
import numpy as np import matplotlib.pyplot as plt x = np.linspace (0, 50, 1000) y = 0.75 * np.sin(x) peaks = np.where((y[1:-1] > y[0:-2]) * (y[1:-1] > y[2:]))[0] + 1 dips = np.where((y[1:-1] < y[0:-2]) * (y[1:-1] < y[2:]))[0] + 1 plt.plot (x, y) plt.plot (x[peaks], y[peaks], 'o') plt.plot (x[dips], y[dips], 'o') plt.show()
A fentiekben egy listát készítünk az összes olyan indexről, ahol y[i] értéke nagyobb, mint mindkét szomszédja.
Nem ellenőrzi a végpontokat, amelyeknek csak egy-egy szomszédjuk van.
A plusz +1 a végén azért szükséges, mert a where az y[1:-1] szeleten belüli indexeket találja meg, nem pedig a teljes y tömböt. A [0] azért szükséges, mert a where egy tömbökből álló tuple-t ad vissza, ahol az első elem a kívánt tömb.
A matplotlib könyvtárat használjuk a grafikon elkészítéséhez.
2. módszer: A numpy.diff használata
A megoldás másik egyszerű megközelítése a numpy beépített függvényének, a "numpy.diff"-nek a használata.
Kód:
import numpy as np
# define an array
arr = np.array([1, 3, 7, 1, 2, 6, 0, 1, 6, 0, -2, -5, 18])
# What "numpy.diff" does, and what is the type of the result?
#print((np.diff(arr), type(np.diff(arr))))
# What "numpy.sign" does?
#print(np.sign(np.diff(arr)))
peaks = np.diff(np.sign(np.diff(arr)))
#print(peaks)
local_minima_pos = np.where(peaks == 2)[0] + 1
print(local_minima_pos)
Definiálunk egy 1D tömböt "arr", majd jön egy egysoros. Ebben először is kiszámítjuk az egyes elemek közötti különbségeket. (np.diff(arr). Ezután a "numpy.sign" függvényt használjuk ezen a tömbön, így megkapjuk a különbségek előjelét. (azaz: -1 vagy 1). Az egészet átadjuk egy másik "numpy.diff" függvénynek, amely +2 vagy -2 vagy 0 értéket ad vissza. 0 érték folyamatos csökkenést vagy növekedést, -2 érték maximumot, +2 érték pedig minimumot jelez. Most már megvannak a csúcsok, és a numpy.where megmondja a pozíciókat. (Figyeljük meg a +1-et a sor végén, ez azért van, mert a csúcsok tömb 0. eleme az arr tömb 0. és 1. eleme közötti különbség. A [0] azért szükséges, mert a "numpy.where" egy tömbökből álló tuple-t ad vissza, ahol az első elem az általunk kívánt tömb).
3. módszer: Megoldás scipy-vel:
Az utolsó példában azt szeretném bemutatni, hogy a scipy könyvtár segítségével hogyan oldható meg a probléma egyetlen sorban.
Kód:
import numpy as np
from scipy.signal import argrelextrema
x = np.linspace (0, 50, 100)
y = np.sin(x)
#print(y)
print(argrelextrema(y, np.less))
A következő bejegyzésben a 2D-s tömbök lokális minimumaival folyatatom.