Kernelalapú móduszbecslés

Tegyük fel, hogy rendelkezésre állnak nem egyenletes eloszlású adatminták. Bár az eloszlást nem ismerjük, de annyit tudunk, hogy folytonos. Tudni szeretnénk, hogy mi az eloszlás módusza.

Folytonos eloszlások móduszának, vagyis a sűrűségfüggvény maximumának ismerete a hétköznapi vagy üzleti életben fontos lehet. Például egy városban a nappali hőmérséklet eloszlásának maximuma nyáron a légkondicionálás vagy szabadtéri rendezvények időzítése szempontjából lehet hasznos. Egy szupermarketben a napi vásárlási összegek eloszlásának csúcsa a kosárérték-optimalizálás szempontjából érdekes, például promóciós vagy árazási stratégiák kialakításához.

Bármilyen célból is vagyunk kíváncsiak a móduszra, az adatmintákból közvetlenül nem tudjuk azt meghatározni, mert az eloszlás nem diszkrét, hanem folytonos. Az is kérdés lehet, hogy van-e egyáltalán módusza az eloszlásnak.

A válasz: igen. Minden folytonos, nem egyenletes eloszlásnak van legalább egy módusza. Vagyis a sűrűségfüggvénynek létezik legalább egy globális maximuma, sőt akár több lokális maximuma is lehet.

Ez a megállapítás szemlélet alapján is belátható. Ugyanis a sűrűségfüggvény egy olyan folytonos, nemnegatív értékű függvény, amelynek görbe alatti területe (integrálja) véges (konkrétan 1). Ha az eloszlás nem egyenletes, akkor a sűrűségfüggvény nem lehet konstans, így:

  1. vagy csak egy korlátos és zárt intervallumban vesz fel pozitív értékeket, másutt 0,
  2. vagy a függvényértéke a pozitív/negatív végtelenben nullához tart, különben az integrálja nem lenne véges.

Mindkét esetben szükségszerű, hogy a sűrűségfüggvénynek legyen maximuma.

Természetesen a fenti állítás egzakt matematikai úton is bizonyítható, de ehhez felsőbb szintű matematikai ismeretek kellenek (az ezt ismerőknek a Weierstrass tételre kell emlékezni).

Ez a kis matematikai előzetes azért szükséges, hogy esetleg ne hiába keressünk móduszt ott, ahol nincs. De most már tudjuk, hogy kell lenni.

Most, hogy ezt tisztáztuk, már ténylegesen megkereshetjük az eloszlás móduszát egy algoritmikus eljárással.

Az egyszerűség kedvéért tételezzük még fel, hogy a sűrűségfüggvénynek csak egyetlen maximuma van, vagyis az eloszlás egymóduszú (unimodális). Ez nem túl szűkítő korlátozás, mert a nevezetes eloszlások többsége (pl. háromszög, béta, gamma, Weibull, normális, lognormális) unimodális. De az alábbiakban bemutatott módszer kis módosítással kiterjeszthető többmóduszú (multimodális) folytonos eloszlásokra is.

A becslési eljárás két fő lépésből áll:

  1. A minták alapján meghatározunk egy közelítő sűrűségfüggvényt
  2. Ennek megkeressük a maximumhelyét, ami az eloszlás becsült módusza lesz.

A sűrűségfüggvény becslésére a magfüggvényes, vagy más szóhasználattal kernelalapú sűrűségbecslési módszert (kernel density estimation, KDE) alkalmazzuk. Ennek elvéről és példákkal illusztrált működéséről a „Magfüggvényes valószínűségi sűrűségbecslés” című korábbi cikkben már volt szó, ezért e módszert itt nem ismertetjük.

A maximumkeresésre az intervallumharmadolós keresési eljárást (ternary search) alkalmazzuk. Ez hasonlít a klasszikus intervallumfelezéses módszerhez, de ennél az eljárásnál – ahogy a neve is utal rá – a keresés során az intervallumot mindig három részre osztjuk. Részletes leírása megtalálható például a „Ternary search” Wikipédia szócikkben, ahol Python nyelvű megvalósítás is szerepel. Ez azonban hibás eredményt adhat, ha a harmadolópontokban a függvényértékek megegyeznek. Ezért mi egy javított változatot használunk, amely kiküszöböli ezt a problémát. A módosítás lényege, hogy egyenlőség esetén a vizsgált intervallumot a harmadolóppontok által határoltra szűkítjük és innen folytatjuk a keresést.

Ami a konkrét megvalósítást illeti, definiálunk egy olyan KDEEstimator nevű osztályt, amelynek példánya fogadja a mintákat, és ezek alapján nem csak a becsült sűrűségfüggvényt tudja szolgáltani egy metódushívással, hanem ennek alapján egy másik metódussal a becsült móduszt is. A magfüggvényes sűrűségbecsléshez alkalmazandó paramétereket a példányosításkor a konstruktorban lehet megadni, de azokat később meg lehet változtatni. Ez lehetővé teszi, hogy adott mintasorozathoz több fajta kernellel is végezzünk számítást. Az osztály definíciója alább látható.

A becslőobjektum működésének teszteléséhez készítünk egy függvényt random_samples() néven, amely a vizsgálandó mintasorozatot állítja elő. Ennek első argumentuma egy olyan hívható objektum, amely minden egyes híváskor egy bizonyos folytonos eloszlásból egy véletlen értéket szolgáltat. Ennek paramétereit lehet felsorolni a random_samples() első argumentuma után. Utolsó argumentumként lehet megadni, hogy hány minta legyen generálva. Ennek alapértelmezett értékét igény szerint állíthatjuk be. A függvény definíciója:

A becsült sűrűségfüggvényt egy grafikonon vizuálisan is meg kívánjuk jeleníteni, amin bejelöljük a módusz helyét és kiírjuk a becsült értékét. Ezt valósítja meg a következő függvény:

A tesztelést többfajta ismert, nevezetes eloszlás mintáival végezzük. Tesszük ezt azért, mert ekkor előre tudhatjuk az elméleti módusz értékét, és így meg tudjuk ítélni a móduszbecslés pontosságát különböző esetekben.

Ehhez első lépésben létrehozzuk a becslőobjektumot mint a KDEEstimator példányát adott kernellel, és sávszélességkorrekciós tényezővel. A nevezetes folytonos eloszlások közül a háromszög, béta, gamma, Weibull, normális és lognormális eloszlásokat fogjuk használni a vizsgálatokhoz. Ezek mintagenerátor függvényeit a szabványos könyvtár random moduljából importáljuk. Az egyes függvényneveket az eloszlást meghatározó paraméterekkel, valamint a megjelenítési intervallum alsó és felső szélével egy-egy tuple-ban fogjuk össze. Ezeket pedig egy listában gyűjtjük össze.

Mindezen előkészítés után egymás után vesszük a tuple konténereket, és kicsomagoljuk a tartalmukat. Az aktuális mintagenerátor függvénnyel előállítjuk a vizsgálandó mintasorozatot, amit átadunk a becslőobjektumnak. Végül, ezt használva megjelenítjük a becsült sűrűségfüggvényt és a becsült móduszt. A tesztkód és az eredmények alább láthatók. Érdemes több futtatást is végezni, hogy lássuk a becslések megfelelőségét.

Megállapíthatjuk, hogy a becsült módusz elég jól közelíti az elméleti értéket. Egyetlen kivétel a lognormális eloszlás, ahol jelentősebb az eltérés.

Ebben a bejegyzésben a nem-paraméteres móduszbecslés egy lehetséges módszerét mutattuk be. A megvalósításhoz a szabványos könyvtár random és statistics moduljainak eszközkészletét használtuk. Ezekről a Python tudásépítés lépésről lépésre című e-könyv „Készétel fogyasztás – a szabványos könyvtár moduljainak használata” fejezet „Matematikai számítások támogatása” alfejezetén belül a „A véletlen használatba vétele” és  „Statisztikai eszköztár” alcímek alatt van részletesen szó, példákkal segítve a megértést. A bemutatott tesztkódot egyszerűsítette a tuple konténerek elemeinek rugalmas kicsomagolási lehetősége. Erről az „Iterálható objektumok értékeinek ki- és becsomagolása” című részben lehet bővebben olvasni.

Érdekel a Python tudásépítés lépésről lépésre az alapoktól az első asztali alkalmazásig című e-könyv.