Materiál k cvičení DBM2 týden #3, sezona 2023/2024
V tomto cvičení je využíván dataset titanic.csv obsahující údaje o pasažérech na lodi RMS Titanic. Význam atributů:
※ Dataset je přejatý z Kaggle soutěže a část datasetu byla vyčleněna do testovací sady bez uvedené hodnoty survived. Možná někde existuje i kompletní sada.
Data jsou v CSV formátu, což není nativní formát pro Weka, nicméně je možné soubor naimportovat. Ve Weka Explorer - Open file lze zobrazit soubory typu csv a daný vstupní soubor zvolit.
Hlavním úkolem je najít, co mají společného lidé, kteří přežili, a na základě toho být schopni predikovat osud nově zadaného pasažéra. Target atributem je survived. Tento atribut je momentálně chápán jako datový typ numeric, což neodpovídá jeho podstatě. Abychom mohli používat metody klasifikace (nikoliv metody regrese), je nutné ho přetypovat na nominal. V našem případě lze použít binární nominal, tj. mající možnost nabývat pouze dvou stavů. Vyberme ve filtrech (1) Filters → Unsupervised → Attribute → NumericToBinary a změňme jeho argument attributeIndices na číslo sloupce survived. Filter je nutné aplikovat tlačítkem Apply. Tlačítkem Edit (6) lze zobrazit viewer, kde survived označíme jako target třídu pravým klikem na sloupec (Attribute as class).
Fig – Rozložení ovládacích prvků na záložce Preprocess.
💾 Takto zpracovaný dataset je vhodné uložit jako soubor typu arff, později poslouží jako baseline při porovnávání užitku různých způsobů předzpracování.
※ Všimněte si, že v uloženém souboru je target sloupec v hlavičce definovaný jako @attribute survived_binarized {0,1}. V datech jsou dále nahrazeny prázdné hodnoty z csv symbolem otazník.
Zkusme pro současný dataset vytvořit klasifikační model. K ilustraci poslouží Naivní Bayes, tj. na záložce Classify volba classifiers → bayes → NaiveBayes.
Q1: Jak funguje Naivní Bayes a jaké jsou jeho předpoklady?
Z výstupu je vidět, že velkou část rozhodovacích vah tvoří jména lidí (které jsou v datasetu jedinečné), ID lístků (547 z 891 záznamů jsou unikátní) a ID kajuty (101 unikátních hodnot). Díky těmto atributům je model teoreticky schopný dosáhnout velké přesnosti predikce při nevhodném učení, nicméně pro predikci nad neznámými daty je toto vesměs irelevantní a pouze zbytečně komplikuje model. Odstraňme tedy tyto atributy. Na Preprocess záložce v sekci s atributy (3) označíme name, ticket, cabin a volíme remove.
💾 Změněný dataset je vhodné uložit pod jiným názvem k pozdějšímu srovnání.
V této fázi je také dobré se podívat na obsah sloupců typu nominal, zda pro stejný fakt nepoužíváme různá označení. Příkladem by mohlo být označení některých žen řetězcem "F" a jiných "Female". Také je vhodné zkontrolovat, že v datech nejsou outliers (pozorování velmi vzdálená od ostatních), případně rozhodnout, co s nimi udělat.
Některé atributy mají v datasetu chybějící hodnoty. Otázka, jak vyřešit tento problém, je často v textech o data-miningu zmiňována, ale neexistuje obecně ideální řešení. Nejčastější možnosti jsou:
V našem případě je problém s atributy embarked (2, 0% chybějící) a age (177, 20% chybějící).
Pro případ embarked se můžeme pokusit podívat, zda na první pohled nejde odvodit místo nástupu z jiného atributu. Nejnadějnější z příbuzných atributů se jeví fare (cena lístku by mohla být mimo jiné závislá na místě nástupu), ticket (dá se očekávat, že skupina lidí jedoucí na jeden lístek nastoupila ve stejném místě), případně cabin. Ani pro jeden atribut ale není v datasetu řádek se shodnou hodnotou. Vzhledem k tomu, že jde pouze o 2 záznamy, což je zanedbatelné množství, jeví se jako nejekonomičtější řádky zahodit. Ve Weka se zahození provede pomocí Filter → Unsupervised → Instance → RemoveWithValues Nastavení je složitější, protože ve filtru potřebujeme nastavit jaké položky zahodit pomocí jejich indexů.
attributeIndex = (číslo atributu embarked);
matchMissingValues = true;
nominalIndices = first-last;
invertSelection = true;
Jelikož nám ale jde o zahození null hodnot, je potřeba nejprve nalézt všechny existující hodnoty (first-last index), invertovat výběr a umožnit zachycení chybějících hodnot.
※ Tuto i další operace by bylo možné udělat (asi pohodlněji) externě přes jiný nástroj. Výhoda úpravy ve Weka je zachování řetězce operací jako metadat v ARFF souboru.
Problém s věkem již nebude možné ignorovat. 20% je značná část datasetu a zároveň se tento atribut zdá důležitým při tvorbě modelu. Zkusme dosadit za chybějící data střední hodnotu atributu. Filter → Unsupervised → Attribute → ReplaceMissingValues nahradí všechny chybějící hodnoty ve všech atributech. Je tedy vhodné tento filter volat až v době, kdy jsou aplikovaná řešení ostatních chybějících hodnot.
Fig - změna histogramu sloupce Age po dosazení střední hodnoty místo chybějících hodnot
Na obrázku je zachycena charakteristika dat ve sloupci age. Všimněte si, že byla změněna směrodatná odchylka a celkový tvar histogramu. Toto řešení může vést ke snížení kvality odhadu pro osoby s věkem kolem 29,6 (kromě "pravých" záznamů teď do kategorie spadají i záznamy, u kterých netušíme, kolik let jim ve skutečnosti bylo).
💾 Takto upravený dataset uložme pod novým jménem.
Některé algoritmy jsou definované pouze pro nominální atributy (např. hledání apriori asociačních pravidel). Můžeme se tedy rozhodnout v rámci preprocessingu pro diskretizaci numerických hodnot. Slouží k tomu Filter → Unsupervised → Attribute → Discretize. Filtr nadefinuje rozsahy číselných hodnot (bin/koš) následně mapovaných do nominálních hodnot. V nastavení filtru je potřeba zvolit:
attributeIndices (seznam čísel atributů, na které filtr aplikovat);
bins (počet kategorií/binů);
useEqualFrequency (definiční obor se rozdělí na N rozsahů se stejnou četností
NEBO na N stejně širokých rozsahů).
Fig - rozdíl mezi diskretizací atributu fare na 10 binů s volbou stejné šířky (vlevo) a stejné četnosti (vpravo)
Aplikujeme filtr na dataset před doplněním středních hodnot za chybějící hodnoty ve sloupci age. V nastavení volíme atributy age, sibsp, parch a fare; a automatický počet binů. Všimněte si, že v každém případě byl zvolen odlišný počet binů.
V atributu age nyní nahradíme chybějící hodnoty novou textovou hodnotou N/A. K tomu slouží filtr Filter → Unsupervised → Attribute → ReplaceMissingWithUserConstant, kde v nastavení zvolíme:
nominalStringReplacementValue = N/A
attributes = (číslo sloupce age).
💾 Soubor s datasetem opět uložte pod jiným názvem.
※ V případě, že v datech máme numerické hodnoty nesoucí význam číselníku, resp. kategorií (jako atribut pclass), je vhodnější použít filtr Filter → Unsupervised → Attribute → NumericToNominal.
Postupně jsme vytvořili 4 datové arff soubory v různých částech preprocessingu.
Zkusme vytvořit experiment, ve kterém zjistíme, zda naše úpravy vedly ke kvalitnějšímu modelu. Ve Weka Experimenter vytvoříme nový experiment, zvolíme klasifikaci a vybereme datasety. Jako klasifikační algoritmy doporučuji zvolit: ZeroR, NaiveBayes, IBk (n=3), J48, RandomForest. Spustíme test a na záložce Analyse načteme výsledky.
Fig — nastavení experimentu
Fig — výsledky experimentu
Jelikož sledujeme rozdíly mezi jednotlivými datasety, tlačítkem Swap se prohodí řádky a sloupce v přehledové matici. Tímto ;je tedy zkoumáno, zda předzpracování mělo vliv na shopnost jednotlivých algoritmů predikovat atribut survived. Jako báze je použit soubor v1, není-li nastaveno jinak.
Q2: Jaké jsou výsledky experimentu? Byly zvolené úpravy datasetu vhodné?