Computer Breakers Informace - NEUROINFORMATICS-GROUP-FAV-KIV-ZCU/guess_the_number GitHub Wiki
Sem dávejte různé výsledky z vašich analýz a poznatky, co jste objevili během vývoje.
##Rozcestník:
Obsah souboru .gitignore by měl být pro náš projekt takový (pokud na něco dalšího narazíme, bude to přidáno):
/bin
/log
.classpath
.gitignore
.project
.settings/
data/best_class_2_650.txt
data/train/set2.eeg
data/train/set2.vhdr
data/train/set2.vmrk
Pozn.: soubor by měl být umístěn v kořenovém adresáři projektu.
Tady budeme řešit uživatelské rozhraní a obecně použití našich klasifikátorů. Důležitá je pro nás proměnná private final IERPClassifier classifier, do které pak v konstruktoru třídy přiřadíme instanci konkrétního klasifikátoru (momentálně je tam instance MLPClassifier). Klasifikátoru se pak předá "trénovací soubor", cesta k němu je v proměnné Const.TRAINING_FILE_NAME. Dál se založí instance třídy pro extrakci příznaku a ta se příslušným setem přiřadí instanci klasifikační třídy.
Až budeme vytvářet GUI, kde bude možnost si vybírat kombinaci klasifikátoru a metody pro extrakci příznaku, budeme tyto dvě proměnné přiřazovat dynamicky. Ohledně vytváření GUI - v metodě private JMenuBar createMenu() si pak přidáme vlastní JMenuItem, co nám bude otevírat nějaké naše okno s nastavením. Toto okno pak bude mít nějspíš vlastní třídu, ve které se vyřeší veškeré další prvky a interakce s klasifikátory. Tato třída pak bude v balíku icp.online.gui.
Každý klasifikátor (celkem budou 4) bude reprezentován třídou dědící od ERPClassifierAdapter. Pokud bude implementace konkrétního klasifikačního algoritmu vyžadovat větší prostor než jednu metodu, bude se pro něj vytvářet další extra třída, jejíž metody se pak budou volat z té zmíněné.
Důležitá je pro nás zejména metoda public double classify(double[][] epoch), která přijme dvourozměrné pole reprezentující 1 epochu získanou z naměřeného signálu. První index značí kanál a na druhém se pak nachází konkrétní hodnota napětí. V této metodě se bude jednak volat metoda ze třídy na extrahování příznaku (předá se jí zmíněná epocha), která vrátí vektor příznaku (více o něm v rozpisu tříd pro extrakci příznaku) a ten se pak zpracuje příslušným algoritmem pro klasifikaci. Metoda pak bude vracet 1 double představující skóre pro zpracovaný příznak.
Dále bude zapotřebí metoda public void train(List<double[][]> epochs, List targets, int numberOfIter, IFeatureExtraction fe), která bude spouštět trénovaní algoritmu. List s epochami je asi celkem zřejmý, List targets pak obsahuje předpokládané výsledky klasifikace pro každou epochu, podle kterých trénování algoritmu proběhne, int numberOfIter je pak počet iterací, pro který bude trénování probíhat (čím více iterací, tím lépe natrénovaný algoritmus), a nakonec parametr s instancí třídy pro extrahování příznaku je asi také jasný. Trénování jako takové závisí na konkrétním algoritmu, jeho implementace bude popsána časem.
Ostatní metody ve třídě jsou celkem zřejmé a v podstatě je stačí použít z již implementovaných klasifikátorů. Veškeré třídy řešící klasifikaci přidávat normálně do balíku icp.application.classification.
Pro každou ze 3 metod extrakce příznaku (WT, MP a HHT) bude vytvořena třída implementující rozhraní IFeatureExtraction. Důležitá je zde zejména metoda public double[] extractFeatures(double[][] epoch), ve které bude vytvořeno jednorozměrné pole typu double představující vektor příznaku. Velikost tohoto vektoru bude záviset na parametrech pro konkrétní způsob extrakce, nicméně přinejmenším pole s počtem kanálů se asi lišit nebude, takže může být natvrdo umístěno v kódu - private static final int[] CHANNELS = {1, 2, 3}.
Způsob zápisu konkrétních hodnot do tohoto vektoru se bude zase lišit podle konkrétního způsobu extrakce, nicméně obecně vzato se jedná o postupné zpracovávání pole double[][] epoch, kde se v rámci prvního indexu prochází podle počtu kanálů (pro nás 3) a jednotlivé jeho "řádky" se pak řeší daným algoritmem a jeho metodami. Pro lepší představu se podívejte do již vytvořených tříd pro extrakci.
Poslední metoda - public int getFeatureDimension() - pak slouží k vrácení velikosti vektoru příznaku, který se bude získávat výše zmíněnou metodou. Třídy pro extrakci budou umístěna v balíku icp.application.classification spolu se třídami pro klasifikaci.
Ve třídě MainFrame
se přidělá do MenuBar
nové FileMenu
(např. nazvané Settings
), ve kterém bude MenuItem
Feature Extractor a Classifier. Po kliknutí na jednu z položek se otevře dialogové okno s možnostmi výběru klasifikátoru nebo extraktoru a jeho parametrů. Klasifikátor a / nebo extraktor se nastaví do používaných proměnných ve třídě MainFrame
a do nové proměnné boolean changed
se nastaví, zda proběhla nějaká změna a tudíž je potřeba klasifikátor natrénovat.
Do MainFrame přidat dvě metody: setCurrentClassifier(IERPClassifier classifier) a setCurrentFeatureExtraction(IFeatureExtraction fe). Ty budou přepínat konkrétní algoritmy, jakmile GUI komponenta pro jejich přepínání (prostřednictvím nějaké své metody na tlačítku) pošle příkaz.
Pro nastavování parametrů pro tyto algoritmy bude zapotřebí k příslušné části GUI implementovat část, která bude kontrolovat jejich správné zadání. Příklad - chci nastavit rozmezí vzorků, pro které budu provádět extrakci epochy - první index nesmí mít vyšší hodnotu než ten poslední. Pro nastavení parametrů se použije parametrický konstruktor / settery implementované v jednotlivých třídách obsahující klasifikátory / extraktory. Při změně parametrů se bude klasifikátor / extraktor zakládat znovu, je třeba jej stejně natrénovat, není tedy nutné mít pro všechno settery, když zmíněné parametry budou v kontruktoru.
-
sampleWindowSize: přes setter public void setSampleWindowSize(int sampleWindowSize); vrací IllegalArgumentException, pokud je <= 0
-
sampleWindowShift: přes setter public void setSampleWindowShift(int sampleWindowShift); vrací IllegalArgumentException, pokud je <= 0
Pozn.: je třeba zajistit, aby platilo vždy (než se zavolají ty settery) sampleWindowShift <= sampleWindowSize a taky aby obojí bylo <=EPOCH_SIZE
-
amplitudeThreshold: přes setter public void setAmplitudeThreshold(double amplitudeThreshold); nevrací žádnou vyjímku
-
minFreq: přes setter public void setMinFreq(double minFreq); vrací IllegalArgumentException při hodnotě <= 0.0
-
maxFreq: přes setter public void setMaxFreq(double minFreq); vrací IllegalArgumentException při hodnotě <= 0.0
Pozn.: je třeba zajistit, aby platilo vždy (než se zavolají ty settery) minFreq <= maxFreq
- typeOfFeatures: přes setter setTypeOfFeatures(int typeOfFeatures); jako hodnoty jsou tam na to připraveny public konstanty AMPLITUDE_FEATURES a FREQUENCY_FEATURES, je třeba zajistit, aby nešly volit jiné (třeba přes výběrový seznam)
- k_cnt: přes konstruktor public KNNClassifier(int k); mělo by se vkládat vždycky alespoň 1