RapidMiner tippek – A Building Block-ok
A tervezettnél egy kicsit hosszabb szünet után újra a billentyűzet mögé ültem blogírás céljából.
A téma továbbra is a RapidMiner, bár mostanában ritkábban használom (használjuk) ezt a szoftvert, ennek ellenére bőven van mit írni róla. Persze itt nem kilométeres “how-to” leírásokra gondolok; – ahogy eddig, úgy ezután is olyan témákat szeretnék elővenni, melyekről máshol nemigen, vagy csak nagyon elvétve lehet olvasni. A korábbi három bejegyzésem néhány apró, de annál inkább zavaró hiányosságot illetve azok megoldásait, kikerülési lehetőségeit tartalmazta. Ezzel szemben a mostani írásom inkább a RapidMiner-ben rejlő egyik nagyszerű képesség kiaknázásáról, nevezetesen a “Building Block-okról” szól.
De mik is azok a Building Block-ok (továbbiakban “BB”)? Nem kell semmi különösre gondolni, ugyanis a név magáért beszél: a BB-ok RapidMiner építőelemek, gyakorlatilag olyan Subprocess-ek, melyeket az aktuális folyamat építésekor – ha valami nagyszerűt hoztunk létre – önállóan el lehet menteni későbbi, más folyamatokban való felhasználásra. A normál folyamatként való elmentéstől abban különböznek, hogy nem process-ként “.rmp” kiterjesztéssel kerülnek eltárolásra, hanem “építőelemként” “.buildingblock” kiterjesztéssel a felhasználó “.RapidMiner5” mappájába (vagyis a mentés során nincs lehetőség más hely megadására). Megjegyzendő, hogy egy BB állomány fájlszinten ugyanolyan XML formátumú adat, mint az “.rmp” kiterjesztésű processz. A két mentési forma közti legnagyobb különbség az, hogy ha egy jól bevált operátor-együttest processzként mentünk el, és később használni szeretnénk, akkor ezt csak egy meglehetősen korlátozott formában tehetjük meg: meg kell nyitnunk ezt a folyamatot, el kell mentenünk más néven, majd hozzá kell látni a teljes folyamat további építéséhez az aktuális feladatunknak megfelelően. Ha közben szeretnénk egy másik, korábban már létrehozott operátor-együttest is felhasználni ugyanebben a folyamatban, akkor arra ilyen formában nincs lehetőség. (Persze bármelyik folyamatot megnyithatjuk, és kimásolhatjuk belőle a megfelelő operátor-együttest.) Ezzel szemben a BB-ok esetén egy elkezdett folyamatba tetszőleges módon, helyen és számban helyezhetünk el elmentett építőelemeket pontosan úgy, mintha azok egyszerű operátorok lennének.
BB-ok elmentéséhez az aktuális folyamatunkban ki kell jelölni a menteni kívánt operátorokat, melyeket bele kell tenni egy tartalmazó (pl. Subprocess) operátorba, majd ezen a tartalmazó operátoron jobb egérgombbal való kattintás után a “Save as Building Block…” opciót kell választani. A megjelenő panelen megadható az építőelem neve, és opcionálisan egy leírás hozzá. Ha a menteni kívánt rész pl. egy Loop operátorban, vagy bármilyen más tartalmazó operátorban van, akkor nem szükséges ezt az egy operátort beletenni egy Subprocess operátorba. Több különálló operátort nem lehetséges elmenteni tartalmazó operátor nélkül, vagyis minden esetben pontosan csak egy darab operátor menthető el, mint BB, de ez természetesen tartalmazhat számos más operátort is. A BB-ok felhasználása hasonló módon történik a mentésükhöz: egy már létrehozott folyamat tervezőasztalára jobb egérgombbal kattintva a “New Building Block” almenüből kiválasztható a kívánt BB. BB-ok mentésekor érdemes figyelemmel lennünk az elmentendő operátorok pozíciójára, ugyanis az elmentett építőelem újra használatakor a RapidMiner tervezőasztalán pontosan ugyanazon pozíción fog megjelenni a BB, mint ahol a mentés pillanatában volt. Ha tehát pl. egy nagy és vertikálisan (vagy horizontálisan) hosszú processz aljáról (vagy jobb végéről) mentünk el néhány operátort BB-ként, akkor egy új folyamatban, mely akár egyetlen operátort sem tartalmaz még, a beillesztett BB nem felül és balra igazítva jelenik meg, hanem az eredeti, vertikálisan (vagy horizontálisan) hosszú folyamatnak megfelelően alul (vagy messze jobb oldalon). Így tehát adott esetben elég sokat kell görgetnünk az egérrel, hogy láthassuk a BB beillesztésének eredményét. A BB-ok pozíciója természetesen utólag is módosítható fájlszinten a “.buildingblock” kiterjesztésű XML fájl – BB neve és leírása utáni – második, “<operator” kezdetű sorának a végén az “x=”10″ y=”10″>” értékek megváltoztatásával.
A RapidMiner 5 tartalmaz néhány beépített építőelemet, melyekkel a bemeneti attribútumok alakíthatók binominális, nominális vagy numerikus típusúvá úgy, hogy közben a hiányzó értékek az átlagértékkel helyettesítésre kerülnek. Illetve találunk még egy-egy lineáris regressziót illetve döntési fát tartalmazó keresztvalidációt is. Megjegyzendő, hogy a RapidMiner 6-os verziójának ingyenes változata nem tartalmaz beépített BB-okat.
Most, hogy tudunk menteni és beemelni építőelemeket a RapidMiner folyamatunkba, talán ideje lenne tisztázni, hogy igazából mire is jók a BB-ok? A RapidMiner szoftver egyik nagy előnye, hogy használatával autodidakta módon meg lehet tanulni számos alapvető adatelemzési eljárást illetve különböző technikák sajátíthatók el, mely tanulási folyamat elején még érdekes kihívás, később egyenesen jóleső érzés, az idő előrehaladtával azonban kellemetlen és fárasztó szükségszerűség ugyanazokat illetve nagyon hasonló módszereket újra és újra “leimplementálni”. Hát…, ez utóbbi érzést kerülhetjük el a BB-ok használatával. Nézzünk is erre gyorsan néhány példát:
Melyik adatbányász ne végzett volna már pl. aggregálást és / vagy osztályozást (stb.) egy adathalmazon, és ha ezt RapidMiner-ben tesszük, melyikünk ne bosszankodott volna a kimeneti attribútumok megmagyarázhatatlan elnevezési konvenciója miatt? (Ezt a bagatell hibát vajon mikor javítják ki végre?) Igen, itt a zárójelek használatára gondolok, amikor pl. egy bemeneti “attr_1” nevű attribútum ‘sum’ aggregációja után egy olyan “sum(attr_1)” elnevezésű attribútumot generál a RapidMiner Aggregate operátora, amit később maga a RapidMiner nem tud helyesen kezelni a zárójelek miatt. Ugyanis egy ilyen attribútumot például lehetetlenség helyesen felhasználni a Generate Attributes operátorban, mivel a névben szereplő “sum()” részt a Generate Attributes a saját függvényének tekinti, így az operátor a már tipikusan a bemenetére nem is kerülő “attr_1” nevű attribútumot szeretné összegezni, amit egyrészt nem tud, másrészt mi biztosan nem ezt szerettük volna, hiszen már korábban elvégeztük ezt a műveletet. Hasonló a helyzet pl. egy osztályozó modell alkalmazásakor is. Megjegyzem, hogy a Radoop szoftver ilyen és ehhez hasonló hibákat nem tartalmaz – nem véletlenül vásárolták fel őket -, a kérdés tehát már csak az, hogy ezek az “apróságok” mennyi idő elteltével szivárognak át a Radoop-ból a teljes RapidMiner szoftverbe.
Tehát RapidMiner esetén minden rendes folyamatban az Aggregate vagy Apply Model operátorokat egy Rename operátornak kell követnie, ahol átnevezzük a “sum(attr_1)” illetve ”confidence(0)” típusú attribútumokat zárójel nélküli változatokra (szóközök és mindenféle egyéb karakterek is kerülendők, vagyis csak a ‘\w’ azaz ‘[a-zA-Z\_0-9]’ karaktereket használjuk). Önmagában csak erre a két-két operátorra létrehozni egy BB-ot felesleges, ugyanis ezt minden esetben ugyanúgy fel kellene konfigurálnunk, mint BB nélküli esetben, hiszen előre nem tudhatjuk, hogy pl. mi az aggregálandó attribútum, vagy egy osztályozásnál mi a célváltozó neve, nem is beszélve arról, ha nem egy aggregációt hajtunk végre, hanem pl. 20-at, 30-at (lásd a lentebbi példát), vagy éppen nem binominális osztályozást végzünk, hanem egy többváltozósat. Ilyen esetekben keletkezhet 10-20-30… darab zárójelet tartalmazó attribútumunk is, melyeket egyesével átnevezni még a RapidMiner XML szerkesztő felületét használva is meglehetősen monoton és kiábrándító feladat. Ha azonban létrehozunk egy Loop Attributes operátor alapú BB-ot, mely operátor ‘attribute filter type’ paraméterében megadjuk a ”regular_expression” értéket, az így megjelenő ‘regular expression’ paraméterben pedig a “.*\(.*\)” értéket (természetesen a kezdő- és záró idézőjelek nélkül), illetve bepipáljuk az ‘include special attributes’ opciót (a “confidence”, “prediction”… szerepkörű attribútumok miatt), akkor végigiterálhatunk a zárójeleket tartalmazó attribútumokon, melyeket makrók segítségével automatikusan átnevezhetünk zárójelek nélküli változatokra anélkül, hogy tudnánk ezen attribútumok darabszámát illetve teljes nevét.
A Loop Attributes operátoron belül szükségünk lesz közvetlenül egymás után két Generate Macro operátorra, ahol az elsőben létrehozunk egy ideiglenes makrót (“m_temp”) az alábbi kifejezéssel: “replaceAll(macro(“l_attribute”), “\\(“, “_”)”, ahol az “l_attribute” változó a Loop Attributes operátor iterációs makrója. Ezzel a művelettel lecseréltük a kezdő zárójelet egy aláhúzás karakterre. A második Generate Macro operátorban hasonlóan járunk el, csak ott már az ideiglenes makró szerepel az iterációs makró helyett, illetve a záró zárójelet cseréljük le egy üres karakterre: “replaceAll(macro(“m_temp”), “\\)”, “”)”. Ne feledjük, hogy a ‘replace()’ függvény nem kezeli a reguláris kifejezéseket, illetve hogy az escape karaktert a zárójel karakterek előtt a Java nyelvre való fordítás miatt duplázva kell alkalmazni. Végezetül már csak egy Rename operátorra van szükségünk, ahol az ‘old name’ paraméterben megadjuk az iterációs makró értékét: “%{l_attribute}”, ami tehát az eredeti, zárójeles attribútum-neveket tartalmazza, a ‘new name’ paraméterben pedig a második Generate Macro operátorban létrehozott makró értékét, amely már zárójel nélküli sztringeket tartalmaz. Miután elmentettük ezt az operátor-együttest BB-ként, minden további folyamatunkba pár kattintással beilleszthetjük azt, elkerülve ezzel a fenti kellemetlenségeket.
Egy másik BB példámban különböző operátorok futási idejét lehet könnyen megmérni és olvasható formára hozni, de a futási idő témaköréről bővebben is érdemes szót ejteni (a RapidMiner ezen a területen is adós még ezzel-azzal), így ennek részletezése egy következő bejegyzésre marad.
BB-ok használata a fentieknél sokkal összetettebb esetekben is elképzelhető, sőt, éppen ilyen folyamatok, projektek során domborodik ki hihetetlen előnyük. Képzeljük el például, hogy egy webportálról valós időben gyűjtünk felhasználói adatokat, melyeken valamilyen elemzést szeretnénk végrehajtani, pl. valamilyen módon osztályoznunk kell a felhasználókat (pl. fog-e vásárolni vagy sem). Ehhez szükségünk van egy olyan modellre, amely előállítja a kívánt kimenetet a valós időben gyűjtött adatok alapján. Egy ilyen feladatnál számos probléma felmerül (pl. annak eldöntése és helyes kezelése, hogy egy felhasználóhoz tartoznak-e már eltárolt rekordok vagy – új felhasználóról lévén szó – nem), melyek megoldása során RapidMiner-ben akár 10-20-30 operátort is fel kell használnunk csupán egyetlen egy részfeladat megoldásakor. Ez többszöröződik azáltal, hogy idősor alapú adatokon tipikusan úgy tanítjuk a modellt, hogy a korábban legyűjtött attribútumokból különböző aggregációk során újakat hozunk létre. És itt ahány bemenetet szeretnénk a hagyományos modellező algoritmusunknak átadni, a fenti 10-20-30 operátoros blokkot annyiszor el kellene készítenünk (a többszörözés történhet az aggregálandó attribútum illetve az aggregáció típusa (pl. sum, count, average…) szerint egyaránt). Ehhez pedig vegyük még hozzá, hogy milyen érzés lehet a teljes folyamatot a nulláról újra felépíteni, ha megváltozik a modellezés feladata (pl. vásárlás előrejelzésről churn analízisre), vagy csak egyszerűen ki szeretnénk próbálni kedvenc osztályozó algoritmusunk hatékonyságát másféle bemeneteken. Nos, ilyen esetekben igencsak jól tud jönni, ha már az elején Building Block-ok létrehozásában gondolkodunk, melyek egyik első operátora célszerűen egy Set Macros, miáltal egyetlen dolgunk beállítani az aggregálandó attribútumot és az aggregáció típusát tartalmazó makrókat, és ezzel egy perc alatt le is gyártottuk a kódját egy újabb jellemzővektor létrehozásának a modell tanításához.
Végezetül két kiegészítést illetve frissítést tennék korábbi írásaimhoz. Az egyik, hogy 2014.10.16-a óta elérhető a Web Mining Extension 5.3.2-es verziója, melyben azonban még mindig nem javították ki az itt említett Crawl Web hiányosságokat (úgy tűnik, a RapidMiner-nél nem olvassák a blogunkat… :-). A másik pedig a numerikus-nominális konverzióról szóló írásomhoz tartozik, miszerint a Transpose operátor meglepő módon helyesen, azaz teljes egészében, csonkolás nélkül alakítja át a valós attribútumokat nominálissá, amennyiben a bemeneti adattábla tartalmaz legalább egy nominális attribútumot is a valós típusúak mellett. Ha nem tartalmaz ilyet, akkor természetesen nincs szükség típuskonverzióra a transzponálás során.
A kép forrása.