České vysoké učení technické v Praze Fakulta elektrotechnická

Transkript

České vysoké učení technické v Praze Fakulta elektrotechnická
České vysoké učení technické v Praze
Fakulta elektrotechnická
Katedra počítačů
Bakalářská práce
Návrhové vzory v aplikaci FAKE GAME
Jakub Weberschinke
vedoucí práce: Ing. Pavel Kordík, Ph.D.
Studijní program: Softwarové technologie a managment, strukturovaný, bakalářský
Obor: Softwarové inženýrství
11.června 2009
Poděkování
Rád bych poděkoval vedoucímu této práce Pavlu Kordíkovi za jeho skvělý osobní přístup. Dále pak svým
rodičům a přítelkyni, bez jejichž podpory by tato práce nemohla vzniknout.
Prohlášení
Prohlašuji, že jsme práci vypracoval samostatně a použil jsem pouze podklady uvedené
v přiloženém seznamu.
Nemám závažný důvod proti užití tohoto školního díla ve smyslu §60 Zákona č. 121/2000 Sb.,
o právu autorském, o právech souvisejících s právem autorským a o změně některých zákonů
(autorský zákon).
V Praze dne 11. 6. 2009.........................................................................................................................
Abstract
This thesis contains introduction to design pattern issues with focus on GoF and GRASP patterns. The
next part contains description of basic terms of data mining with characterization of Fake Game and Weka
apllications. Describes the most used methods of evaluation of data mining models and compares the former
applications in this respect. Introduces current problems of Fake Game API and discusses possible solutions.
The last part is a description of an integration of Weka evaluation module into Fake Game.
Abstrakt
Obsahem práce je úvod do problematiky návrhových vzorů se zaměřením na GoF a GRASP vzory. Další
částí je popis základních termínů oblasti data miningu s popisem programů Fake Game a Weka. Popisuje
hlavní metody evaluace data miningových modelů a v tomto ohledu blíže srovnává obě dvě aplikace.
Nastiňuje aktuální problémy programu Fake Game API a diskutuje možná řešení. Poslední část popisuje
integraci evaluačního modulu z Weka do Fake Game.
Obsah
Úvod...................................................................................................................................................16
Popis problému, specifikace cíle........................................................................................................18
Popis problému..............................................................................................................................18
Specifikace cíle..............................................................................................................................18
Teorie..................................................................................................................................................20
Data mining....................................................................................................................................20
Fake Game................................................................................................................................21
Weka..........................................................................................................................................21
GRASP vzory.................................................................................................................................21
GoF vzory......................................................................................................................................23
Creational Patterns....................................................................................................................23
Structural Patterns.....................................................................................................................25
Behavioral patterns...................................................................................................................27
Analýza evaluačních metod a metrik.............................................................................................32
Hold-out....................................................................................................................................32
K-fold křížová validace.............................................................................................................33
Leave-one-out...........................................................................................................................33
Validace opakovaným vytvářením náhodných vzorků.............................................................33
Bootstrap...................................................................................................................................34
Metriky...........................................................................................................................................34
Chyba........................................................................................................................................34
Zaujetí.......................................................................................................................................34
Variance.....................................................................................................................................35
Matice záměn............................................................................................................................35
Evaluace klasifikace..................................................................................................................35
Matice cen.................................................................................................................................36
ROC křivka...............................................................................................................................36
AUC..........................................................................................................................................37
Ostatní metriky..........................................................................................................................37
Analýza...............................................................................................................................................38
Základní stavba Fake Game...........................................................................................................38
Problémy spojené se současnou verzí.......................................................................................38
Analýza evaluačních metod ve Fake Game...................................................................................39
Evaluace modelů přes metodu saveToFile().............................................................................39
Evaluace modelů pomocí balíčku preprocessing.statistic.........................................................41
Evaluace v programu Weka...........................................................................................................43
Návrh & Implementace......................................................................................................................45
Diskuse možných postupů.............................................................................................................45
Propojení Weka a Fake Game........................................................................................................45
Diskuse......................................................................................................................................45
Řešení........................................................................................................................................46
Úprava balíčku preprocessing.statistic..........................................................................................48
Diskuse......................................................................................................................................48
Řešení........................................................................................................................................48
Grafické rozhraní používající evaluaci z Weka.............................................................................50
Diskuse......................................................................................................................................50
Řešení........................................................................................................................................50
Testování.............................................................................................................................................52
Manuální testování.........................................................................................................................52
Unit testy s běžnými objekty.........................................................................................................52
Unit testy s mock objektem...........................................................................................................53
Závěr...................................................................................................................................................54
Literatura............................................................................................................................................56
Seznam použitých zkratek..................................................................................................................58
Uživatelská příručka...........................................................................................................................60
Obsah CD...........................................................................................................................................62
Seznam obrázků
ROC křivka klasifikačního modelu....................................................................................................36
kvalita klasifikace vyjádřená metrikou AUC (křivky shora: skvělá, dobrá, špatná)..........................37
UML diagram základních modulů Fake Game..................................................................................38
vzorek kódu metody saveToFile() objektu TreeData.........................................................................39
UML diagram tříd, které využívají metodu saveToFile()...................................................................40
UML diagram tříd, které se v modulu statistics podílí na evaluaci....................................................42
modul statistického balíčku s maticí záměn a statistikami souvisejících metrik................................42
modul statistického balíčku zobrazující bias a varianci.....................................................................43
třídy spolupracující na evaluaci v programu Weka............................................................................44
UML diagram znázorňující balíček adaptérů.....................................................................................46
UML diagram výjimek a jejich původců............................................................................................47
UML diagram statistic.core................................................................................................................49
UML diagram vztahů GUI a datových tříd balíčku statistic ..............................................................49
grafické rozhraní modulu Weka Evaluation.......................................................................................50
vzorek kódu testů................................................................................................................................52
Seznam tabulek
matice záměn pro tři třídy...................................................................................................................34
matice cen pro tři generické třídy.......................................................................................................35
Kapitola 1
Úvod
V posledních letech si zejména velké společnosti, které disponují rozsáhlými databázemi s
obrovským množstvím dat o klientech, produktech, obchodech, atp., začaly uvědomovat cenu
informací v nich skrytých. A velice záhy také zjistily, že zdaleka nejcennější jsou ty informace,
které nejsou na první pohled zřejmé. Začaly se hledat metody, jak co možná nejrychleji a
nejefektivněji odhalit tyto skryté informace a tak z nich moci vytěžit co největší prospěch. A to je
přesně ten důvod, proč oblast data miningu, v Čechách též známá jak vytěžování dat, zažívá v
poslední dekádě takový rozmach.[14]
Postupně se vytvářely nové a lepší postupy, jak odkrývat a popisovat tyto na první pohled
nezřejmé vztahy, které byly pochopitelně čím dál tím víc složitější. A tak se začal řešit ještě jeden
problém: vytvořit co možná nejjednodušší, ale zároveň výstižný systém, který by byl schopen
porovnat úspěšnost více rozdílných data miningových technik mezi sebou a určit tu vhodnější pro
daný problém.
Odpovědí na tento problém se staly evaluační metody. Nejdříve se jednalo o statistické metody,
které původně vznikly pro potřeby jiných odvětví, ale postupně se vytvářely i postupy přímo pro
data mining jako takový. Není tedy divu, že aplikace, které se zabývají vytěžováním dat, se snaží v
co největší míře implementovat tyto metody.
Krom vyšší kvantity je samozřejmě cílem i vyšší kvalita, a to jak po stránce evaluačních metodik
a metrik, tak po stránce jejich implementace. Trendem je směřování k vyšší přehlednosti,
znovupoužitelnosti a rozšiřitelnosti.
15
16
Kapitola 2
Popis problému, specifikace cíle
Popis problému
Řešeným problémem této bakalářské práce je popsání aktuálního stavu programu Fake Game po jeho
implementační stránce se zaměřením na evaluaci modelů vytvářeních právě v rámci této aplikace. Úkolem je
rozšířit poskytované evaluační metody a spolu se stávajícími je sjednotit pod společné rozhraní. Pokud to
bude možné, bude snaha o maximální použití již implementovaných a otestovaných modulů programu Weka.
Návrh by měl respektovat zásady programování na základě GRASP a GoF vzorů tak, aby byl kód přehledný
a efektivní. Program bude napsán v programovacím jazyce Java.
Specifikace cíle
Prvním krokem práce je blízké seznámení se s principy programování s použitím GoF a GRASP vzorů.
Popíši jejich možnosti užití i případné úskalí, které může jejich aplikace přinést, stejně jako konkrétní
výhody, které z jejich používání plynou. Tyto budou v následujících částech použity jako vzory pro úpravu
kódu aplikace a navržení kódu nového.
Dalším krokem bude popis dostupných metodik a metrik, které se váží k evaluaci modelů v data miningu.
Bude potřeba zjistit, jaké metody jsou nejúčinější v jakém kontextu a za jakých podmínek naopak není jejich
použití nejvhodnější. Důležitým aspektem je také posouzení srozumitelnosti, protože všechny výstupy těchto
metod budou analyzovány přímo uživatelem aplikace.
Následně je nutné analyzovat aktuální stav v aplikaci Fake Game. To bude zahrnovat nejprve pochopení
těch procesů, kterými v rámci zpracování dat aplikace prochází. Následovat bude prozkoumání hlavních
problémů, které má aplikace po implementační stránce, protože je velice pravděpodobné, že s těmito se bude
nutné vypořádat i při návrhu konkrétního rozšíření.
Poté bude žádoucí porovnat mezi sebou aplikace Fake Game a Weka, co se týče jejich řešení evaluačních
problémů. Zde bude nutno zohlednit znalosti získané studiem návrhových vzorů, aby bylo nastínit i případná
řešení nalezených nedostatků. V této části bude také určeno, jaké části se použijí.
Následuje identifikace nedostatků částí, u kterých bylo rozhodnuto, že budou v systému ponechány a
návrh jejich úpravy tak, aby splňovali zásady GRASP. Zároveň bude proveden návrh adaptérů tak, aby bylo
možné používat funkcionalitu programu Weka v GAME.
Nakonec bude provedena samotná implementace. Podle použitých částí bude vybrán nejvhodnější způsob
testování a ten bude použit.
17
18
Kapitola 3
Teorie
Data mining
Pojem data mining, česky vytěžování dat, je „netriviální proces identifikace pravdivých, dosud
neznámých, potenciálně využitelných a naprosto srozumitelných vzorů v datech“1. To znamená, že v datech
hledá vztahy, které nejsou na první pohled patrné a jejichž znalost nám pomůže v dosažení určitého cíle.
Jednotlivé vzorky dat se nazývají instance, jejich vlastnosti jsou pdotom vyjádřeny atributy, které zpravidla
bývají vyjádřeny číselnou hodnotou. [9]
Problémy, které data mining řeší, se rozdělují do několika skupin:
1. klasifikační problémy, kdy se snažíme jednotlivé instance dat podle hodnot jejich atributů přiřadit
do jedné z předem určených tříd. Příkladem klasifikace může být určování zdravotního stavu
pacienta podle jeho příznaků, kdy třídy jsou pak jednotlivé nemoci.
2. regrese, kde z hodnot atributů matematickými operacemi získáváme numerický výstup. Zde je jako
příklad možno uvést zkoumání vlivů jako je cena výrobku, cena u konkurence a inflace
na prodejnost produktu firmy.
3. predikce používá postupy regrese i klasifikace, zde jsou data chronologicky seřazena a z vývoje
jejich hodnot v minulosti určujeme hodnoty budoucí. Příkladem může být předpověď počasí, kdy
z vývoje naměřených meteorologických hodnot určujeme předpokládané teploty na další dny.
4. shlukování je pak další typ, který je podobný klasifikaci. V tomto případě ale nejsou předem určené
skupiny, do kterých se data zařazují, ale cílem je odhalení skupin nebo shluků dat s podobnými
atributy a interpretace těchto míst hustšího výskytu instancí. Problémy tohoto typu se velice často
řeší v oblasti marketingu, například při určování skladby trhu, kdy se identifikují cílové skupiny
zákazníků a vlastnosti, které danou skupinu charakterizují.
5. asociační pravidla se používají k odhalení vnitřních závislostí dat nebo podskupiny dat, tedy to, zda
je hodnota atributu ovlivněna hodnotami jiných atributů v rámci jednotlivých instancí. Toho pak lze
využít u jedné z nejznámější úlohy data miningu, kdy se v obsahu nákupních košíků zákazníků
supermarketů hledají závislosti, na základě kterých se pak upravuje umístění jednotlivých druhů
zboží, aby zákazník musel projít co největší část obchodu.
6. bagging & boosting jsou techniky, které se používají ke kombinování více modelů dohromady.
Do vytěžování dat samozřejmě patří ještě další metody, ale výše uvedené patří mezi nejznámější.
U většiny problémů si data mining vystačí s klasifikací, predikcí a regresí. [12]
Data, která se v oblasti vytěžování používají, často nejsou v původním stavu vhodná k vytváření modelů.
Aby bylo možné jejich matematické zpracování, musí většinou projít procesem zvaným preprocessing. Ten
má za úkol nahrazení textových hodnot číselnými, označení chybějících hodnot, odstranění duplicit
a podobně. Někdy může být jeho součástí i doplnění dalších instancí vygenerovaných na základě těch, které
máme k dispozici.
K získávání znalostí z dat se používají tzv. modely. Ty v případě klasifikačních metod odpovídají
matematickým funkcím více proměnných, kde hodnoty atributů jedné instance jsou proměnné a výstup
odpovídá funkční hodnotě. V ostatních případech se používají různé statistické modely, nástroje na určení
podobnosti atributů na základě vzdálenosti (ať už eukleidovské manhattonské) atp.
U klasifikačních metod používáme k vytváření modelů trénovací data, jejich správnost potom ověřujeme
na testovacích datech. Obě tyto množiny dat musí mít stanovené správné výstupy, v trénování se tyto
používají k hledání optimální přenosové funkce, při testování se pak zjišťuje odchylka očekávané hodnoty
1
Definice Fayyad et al.
19
podle modelu a její hodnoty skutečné. [9]
Poznámka: V této práci často používám, zejména v kontextu data miningových softwarů, termín
klasifikace nebo klasifikační problém. Vzhledem k tomu, že se často používá v širším kontextu, abych
předešel nejasnostem, budu používat dva termíny s odlišným významem. Souslovím klasifikační metody
budu označovat metody, které řeší problémy, kde na základě vstupů určujeme výstup, u kterého je možno
objektivně určit jeho správnost. Tímto je tedy myšlena skupina, do které lze zařadit klasifikaci, regresi
a predikci. V případě, že budu mít na mysli konkrétní metodu, budu používat mluvit pouze o klasifikaci.
Fake Game
Fake Game je data miningový software od skupiny Computational Intelligence Group na katedře
počítačů. Jeho vývoj probíhá v programovacím jazyce Java SE , jeho grafické rozhraní je ovládáno přes
grafické rozhraní, které pracuje nad komponenty Swing. Poslední vývoj směřuje také k používání Java
anotací.
Program se skládá ze dvou hlavních částí. Jádrem je rozhraní Game, které zajišťuje samotné vytváření
modelů, případně ensemble modelů, nad daty. Program umožňuje jak tvorbu modelů jednoduchých, kdy
vstup je na výstup překládán pouze jednou matematickou funkcí, tak i složitých modelů GAME, kdy dochází
ke skládání více funkcí za pomocí neuronových sítí a genetických algoritmů. Takto generované modely pak
na základě předloženého pole reálných čísel vrací jeden reálný výstup. Toto rozhraní umožňuje další práci
s těmito modely, jako je vizualizace či základní evaluace. [5]
Druhou částí je pak Fake, které má za úkol maximální automatizaci celého procesu, od předzpracování
dat až k nastavení parametrů trénovacích algoritmů.
Obě dvě tyto části mají společné grafické rozhraní, ve vývoji je také rozhraní příkazové řádky.
Automatizaci, poskytovanou Fake, je tak možné použít jen některé operace v procesu a zbylé provádět ručně.
Weka
Nástroj Weka je data miningový software vyvíjený skupinou z univerzity Waikato na Novém Zélandu.
Stejně jako předchozí program je programován v jazyce Java, grafické rozhraní je vytvořeno na základě
frameworku Swing. Krom rozhraní grafického může být ovládán také přes rozhraní příkazové řádky.
Program Weka disponuje třemi uživatelskými rozhraními. Základem je prostředí Explorer, které
umožňuje základní operace s prostředím, které do značné míry odpovídají funkcím GAME. Jedná se
o tvorbu modelů, jejich hodnocení a následné zobrazení výsledků. Také poskytuje možnost provedení další
analýzy dat, jako je například shluková analýza, analýza atributů. [3]
Další části, Experimenter a KnowledgeFlow, jsou pouze rozšířením předchozího a nabízejí větší volnost.
Experimenter umožňuje práci s větším množstvím datových zdrojů najednou, zároveň dovoluje použití
většího množství klasifikátorů – je ale velice výpočetně náročná a proto se nehodí k běžnému používání.
KnowledgeFlow naopak znamená posun k většímu uživatelskému komfortu, protože nabízí plnou vizualizaci
procesu zpracování. Všechny úkony jsou reprezentovány ikonami, jejichž spojováním se vytváří posloupnost
spustitelných instrukcí, které jsou překládány na vnitřní volání metod programu.
Rozhraní těchto částí programu jsou plně nezávislá a navzájem se nijak neovlivňují.
Zcela odděleny jsou také jednotlivé funkční moduly, kam patří předzpracování dat, tvorba klasifikátorů,
shlukování, tvorba asociačních pravidel, analýza atributů a vizualizace. Sdílejí jen rozhraní pro načítání
a ukládání dat. Každou z těchto částí je pak možno používat nezávisle na zbytku systému.[4]
GRASP vzory
GRASP (Obecné vzory přidělování odpovědností v softwaru) se poprvé objevily v knize Applying UML
and Patterns Craiga Larmana. Jedná se o nejobecnější z návrhových vzorů, neboť popisují metodiku
přidělování odpovědností jednotlivým třídám, a jen v omezené míře říkají, jaké konkrétní třídy máme
20
používat. Z tohoto důvodu jsou vzory GRASP také někdy označovány jako zásady (principles) nebo procesní
vzory (process patterns). Všechny uvedené vzory jsou obsahem knihy [1].
Mezi GRASP patří následující vzory:
Information Expert
Vzor určující, které třídě máme přiřadit zodpovědnost za úkol, který již máme určený. Říká,
že odpovědnost by měl nést informační expert, to znamená třída, která má k provedení úkolu nejvíce
informací.
Creator
Tento vzor řeší, jaká třída má mít za úkol vytváření instancí jiných tříd. Třída A je tedy tvůrcem třídy B,
pokud platí, že: A agreguje B (tudíž B je součástí A), A komponuje B (B nemá jiné užití než ve vazbě s A),
A zaznamenává instance B, A úzce používá objekty B, A má k dispozici inicializační data potřebná k tvorbě
instance B.
Controller
Určuje, kdo bude zpracovávat událost v systému. Pokud se stane, že program musí reagovat na události,
které mají původ mimo systém, neměl by je nutně zpracovávat objekt, který je jejich příjemcem. Vzor
Controller nabízí dvě varianty určení třídy, která by se měla starat o zpracování: třída, která reprezentuje celý
přijímající systém nebo třída, která představuje scénář případu užití v rámci kterého k události došlo.
Protected variations
Zabývá se problém přiřazování odpovědností tak, aby v případě změn v programu nedošlo k nežádoucím
dopadům na ostatní součásti softwaru. Řešením je určení bodů možných změn a přiřazení odpovědností tak,
aby bylo kolem tohoto bodu vytvořeno neměnné rozhraní. Tímto je míněn interface v širším slova smyslu –
v důsledku se může jednat o rozsáhlý subsystém.
Low Coupling
Tento princip říká, že bychom se měli snažit maximálně snížit závislost mezi třídami, čímž dojde
k omezení dopadu změn v rámci jedné třídy na třídy okolní a zvýšení znovupoužitelnosti. V jazyce Java se
tohoto dosahuje předáváním interface místo konkrétních implementací.
High Cohesion
Coheze je v kontextu objektového programování míra toho, nakolik spolu souvisí úkoly, které má objekt
vykonávat, a jak moc jsou specializované. Snahou vysoké koheze je zvýšení přehlednosti, pochopitelnosti
a robustnosti programu. Příkladem nízké koheze je slučování dat a jejich grafické reprezentace do jedné
třídy.
Polymorphism
Říká, že pokud se chování daného objektu liší, pokud se liší i typ objektu, pak je nutné toto řešit pomocí
dědění od rodičovské třídy, kde konkrétní implementace chování konkrétního typu je definována v rámci
potomků. V Javě se často problémy tohoto typu chybně řeší pomocí pomocných proměnných obsahujících
typ a rozdělením různých funkcionalit v metodě pomocí switch.
21
Pure Fabrication
Jako třída Pure Fabrication se označuje taková, která nemá svůj obraz v problémové doméně a která byla
vytvořena, aby bylo vyhověno zásadám High Cohesion a Low Coupling. Návrhové vzory jako jsou GoF jsou
tvořeny prakticky výhradně takovými třídami.
Indirection
Aby se snížila provázanost objektů, ve kterých může dojít ke změně, používají se třídy, které slouží jako
prostředníci. Tyto třídy zpravidla umožňují jednomu objektu pomocí obecných metod volat? složitější
metody jiného objektu, přičemž tyto metody jsou určeny parametry předávanými metodám prostředníka.
GoF vzory
GoF (Gang of Four) vzory jsou pojmenovány podle čtveřice autorů, kteří je poprvé definovali v knize
Dessign Patterns: Elements of Reusable Object-Oriented Software. Jsou to Erich Gamma, Richard Helm,
Ralph Johnson a John Vlissides. GoF vzory jsou rozděleny do tří kategorií podle toho, jakou skupinou
problémů se zabývají. Všechny tyto vzory jsou uvedeny v knize [2].
Creational Patterns
Jsou vzory, které se zabývají vytvářením nových objektů a jejich správou. Třídy, které jsou na základě
těchto vzorů vytvořeny, plní dvě zapouzdřovací funkce: jednak skrytí toho, jaké konkrétní třídy software
používá, ale také toho, jak jsou jednotlivé instance vytvářeny a sestavovány dohromady.
Abstract Factory
Poskytuje rozhraní pro vytváření skupin souvisejících nebo závislých objektů bez specifikace jejich
konkrétních tříd. Tento vzor se používá, pokud platí, že:
• systém by měl být nezávislý na tom, jak jsou jeho produkty vytvořeny, skládány a reprezentovány
• systém by měl být tvořen vždy jednou z více skupin objektů
• skupina souvisejících objektů je určena k používání jako celek a toto omezení musí být splněno
za každých okolností
• chceme poskytnout třídní knihovnu objektů, jejichž rozhraní má být odkryto na rozdíl od implementace
Princip tohoto vzoru spočívá v tom, že vytvoříme abstraktní třídu či rozhraní, které definuje, jaké obecné
typy souvisejících objektů chceme instanciovat. Tyto jsou definovány pomocí rozhraní. Potomci abstraktní
továrny potom vytvářejí konkrétní objekty, které jsou definovány v třídách implementujících rozhraní.
Aplikací tohoto vzoru dosáhneme izolace konkrétních tříd, zjednodušíme výměnu skupin objektů
a zajistíme konzistenci používaných objektů, protože nehrozí, že by zároveň byly použity dva objekty
z různých skupin. Přidávání nových typů objektů je ale relativně složité, neboť musí dojít ke změně rozhraní
a tím pádem i změnám ve všech třídách, které ho implementují.
Builder
Snahou tohoto vzoru je oddělit tvorbu komplexního objektu od jeho reprezentace tak, aby samotný
konstrukční proces mohl vytvářet různé reprezentace. Měl by se použít, pokud platí některý z těchto případů:
• algoritmus pro vytváření komplexních objektů by měl být nezávislý na částech, ze kterých se objekt
skládá, a na tom, jak jsou sestavovány
• proces vytváření objektu musí umožnit rozdílné reprezentace objektu
22
Jádro tohoto vzoru tvoří tři skupiny objektů: ředitel, stavitel a produkt. Produkt je objekt, který chceme
sestavovat; je zpravidla komplexní, skládá se z více částí. Funkcionalita poskytovaná stavitelem je určena
abstraktní třídou, potomci této třídy překrývají její abstraktní metody. Stavitel poskytuje metody, které se
použijí při sestavování objektu, ale sám je nepoužívá. Ředitel se stará o provedení dílčích kroků sestavování,
k tomu používá rozhraní poskytované stavitelem.
Použitím tohoto vzoru získáme možnost změny vnitřní reprezentace objektu, neboť ta je před uživatelem
skryta, zároveň oddělíme kód tvorby objektu od jeho reprezentace, protože tvorbu má na starosti nezávislá
třída. Také poskytuje jemnější kontrolu nad procesem konstrukce instancí, protože ty jsou vytvářeny krok
po kroku.
Factory Method
Cílem je definovat rozhraní pro vytváření objektů, ale zároveň ponechat na objektech, které ho
implementují, aby určily, jaké konkrétní třídy se mají instanciovat. Je vhodné aplikovat jej v těchto
případech:
• třída předem neví, jaký typ objektu má vytvářet
• potřebujeme, aby potomci třídy specifikovali objekty, které třída vytváří
• třídy delegují odpovědnost na jednoho z mnoha pomocných potomků a my chceme zjistit, který
z potomků je momentálně delegován
Tento vzor má několik implementačních variant, všechny však pracují s třídou produktu a tvůrce,
od nichž se odvozují všechny ostatní. Produkt je abstraktní, jeho potomci jsou konkrétními objekty, které
chceme vytvářet. Tvůrce pak definuje tovární metodu, která vrací produkt. Jednou variantou pak je definovat
tovární metodu jako abstraktní a používat pouze potomků, druhou variantou je používání rodičovské tovární
metody pro vytváření nějakého konkrétního produktu. Další z možných úprav tohoto vzoru je
parametrizovaná tovární metoda, kde je typ vracených produktů určován parametrem metody.
Důsledek tohoto vzoru je větší flexibilita při vytváření objektů a jejich snažší úprava a také větší
přehlednost vztahů mezi jednotlivými typy objektů.
Prototype
Vytváří nové objekty pomocí prototypových instancí a jejich následného kopírování. Měl by být použit
za předpokladu, že systém má být nezávislý na tom, jak se jeho produkty tvoří, sestavují a reprezentují a je
také splněna alespoň jedna z těchto podmínek:
• třídy, které se mají instanciovat, jsou určeny až za běhu aplikace
• nechceme tvořit složitou hierarchii továren kopírující hierarchii produktů
• instance třídy mohou nabývat jen omezených kombinací stavů a chceme ušetřit zdroje potřebné
k opakovanému vytváření nových instancí s odpovídajícím stavem.
Tento vzor pracuje s třídou produktu, který definuje klonovací metodu (v jazyce Java se jedná o metodu
clone()). Konkrétní produkty jsou potomci této třídy, klient je klonuje pomocí rozhraní, které poskytl jejich
rodič.
Výhody prototypu se v mnohém shodují s výhodami abstraktní továrny a stavitele. Jeho další přednosti
ale vyniknou spíše v jazycích, které neumožňují práci s třídami jako objekty. Objektový přístup ke třídám lze
totiž použít k řešení těchto problémů.
Singleton
Zajišťuje, že třída bude mít vždy právě jednu instanci a poskytuje k ní jeden globální přístupový bod.
Je to jeden z nejčastěji používaných vzorů. Používá se v případech, kdy potřebujeme:
23
• aby existovala právě jedna instance třídy a klienti k ní mohli přistupovat přes veřejně známý přístupový
bod
• aby tato instance byla rozšiřitelná potomky a klient mohl tuto rozšířenou instanci používat bez úpravy
jejich kódu.
Jedináček se realizuje tak, že jeho konstruktor skryjeme, čímž zajistíme, že jej klient nebude moci
vytvořit. V jazyce Java toho dosáhneme označením konstruktoru jako private. Pokud chceme pracovat s více
typy jedináčků a z nich vybírat až za běhu, jedna z možností je práce s registrem jedináčků, který je sám
jedináčkem. Přístupů pro práci s jedináčky je více, ale tento je z nich nejflexibilnější a nejvíce „objektový“.
Používání jedináčků přináší celou řadu výhod. Krom snadného zajištění vytvoření právě jedné instance je
to zpřehlednění kódu snížením počtu globálních proměnných, které bychom museli jinak použít. V případě
použití registru potomků je to navíc možnost zvolení konkrétního typu jedináčka za běhu. Oproti použití
statických třídních operací získáváme větší přizpůsobivost například v tom, že můžeme pracovat i s jiným
počtem instancí než jenom jednou, což může být v některých případech výhodné.
Structural Patterns
Zabývají se skládáním tříd a objektů do větších celků. V případě tříd je to používání dědičnosti za účelem
vytvoření nových rozhraní nebo implementací. V případě objektů je to popis, jak složit více objektů
k vytvoření nové funkcionality.
Adapter
Smyslem tohoto vzoru je přizpůsobit rozhraní třídy tak, aby bylo schopné fungovat s klientem, který
očekává jiné rozhraní. Je dobré ho použít za těchto předpokladů:
• chceme použít existující třídu, ale její rozhraní nevyhovuje našim potřebám
• chceme vytvořit třídu, která bude znovupoužitelná i v případě práce s nyní neznámými nebo
nedefinovanými třídami
• chceme používat dědičnost, ale nechceme pro každý objekt zvlášť upravovat rozhraní.
Ať už se volí jakákoli z implementačních variant tohoto vzoru, vždy je dobré mít na paměti, že bychom
se vždy měli snažit pracovat s co možná nejužším rozhraním. Tedy takovým, které plní co nejmenší počet
funkcí. Rozsáhlejší rozhraní bývají zpravidla nepřehledná, proto je lepší preferovat malá a specializovaná.
Jeden adaptér je pak tvořen abstraktní třídou nebo rozhraním, které definuje abstraktní metody, které
požaduje klient. Jeho potomci potom implementací těchto metod určují, jak se klientův požadavek bude
překládat do rozhraní adaptované třídy.
Krom možnosti úpravy rozhraní má tento vzor ještě dvě výhody: dokáže měnit rozhraní více tříd
v případě, že používáme dědičnost (adaptér lze použít i na všechny potomky). Také ztěžuje obcházení funkcí
třídy, na kterou je adaptér použit.
Bridge
Cílem tohoto vzoru je oddělit abstrakci od implementace tak, aby se tyto dvě mohly libovolně měnit
nezávisle na sobě. Most bychom měli použít, pokud :
• chceme zabránit provázanosti abstrakce a implementace. Často tomu tak je, pokud chceme
implementace měnit za běhu programu
• jak abstrakce, tak implementace má být rozšiřitelná děděním
• změny v abstrakci by se neměly dotknout klientů (např. vynucením přepsání části kódu klienta).
Implementace tohoto vzoru je velice jednoduchá. Místo jedné hierarchie tříd zavedeme hierarchie dvě. Ta,
která představuje implementaci, se odkazuje na tu, která představuje abstrakci.
24
Kromě výše zmíněných dopadů přináší použití mostu několik dalších pozitiv. Mimo jiné to je lepší
strukturování systému, protože tento vzor podporuje zavádění vrstev (implementace je součástí vyšší vrstvy
než abstrakce) a odstínění klienta od vnitřní struktury kódu, který používá.
Composite
Skládá objekty do stromových struktur tak, aby reprezentovaly hierarchie se vztahy část-celek. To
umožňuje přistupovat ke všem jednoduchým i složeným objektům uniformě. Po tomto vzoru bychom měli
sáhnout, když:
• chceme vytvořit hierarchii, která v sobě obsahuje vazbu typu část-celek
• chceme, aby klienti nemuseli rozlišovat mezi objekty jednoduchými a objekty složenými
Hlavním prvkem tohoto vzoru je komponenta, která je abstrakcí jak jednoduchého objektu, tak objektu
složeného. Definuje standardní chování vlastní všem objektům hierarchie, včetně metod potřebných pro
sestavování složených objektů. Tyto metody jsou v komponentě zpravidla prázdné a jsou potom u složených
objektů přepsány tak, aby skutečně vykonávaly svou funkci (přidávaly objekty apod.).
Kompozita určuje hierarchie, které obsahují jak objekty jednoduché, tak objekty složené z těchto
jednoduchých objektů, ale i jiných objektů složených. Tím zjednodušují kód na straně klienta, který
nerozlišuje, s jakým typem objektu pracuje; často to ani neví. Také umožňuje snadné přidávání nových tříd,
protože máme jasně dáno, co musí nové typy objektů splňovat. Toto ale s sebou nese určitá rizika, neboť je
obtížnější omezovat nové typy objektů (můžeme například vyžadovat, aby spolu dvě konkrétní třídy
netvořily složený objekt).Proto musíme počítat s nutností provádět některé kontroly za běhu.
Decorator
Dynamicky přiřazuje objektům dodatečnou funkcionalitu a poskytuje flexibilní alternativu k dědičnosti.
Používá se tam, kde:
• chceme zajistit dynamické a transparentní přidělování odpovědností objektu, aniž bychom ovlivnili
okolní objekty
• je zapotřebí funkcionalita, kterou je možné odstranit za běhu
• je použití dědičnosti nepraktické; zejména se jedná o případy, kde by přidáním nových funkcí neúměrně
narostl počet tříd.
Tento vzor pracuje s třídami komponent, to jest objektů, kterým chceme přidávat funkcionalitu. Ty dědí
od rodičovské abstraktní komponenty, od které také dědí abstraktní dekorátor, jehož potomci potom
představují právě přidávanou funkci nebo stav.
Výhodou oproti statickému přístupu v podobě přidávání funkcí pomocí dědičnosti je to, že se jedná
o výrazněji flexibilnější způsob. Dekorátory totiž umožňují své kombinování, takže jednomu objektu
můžeme přidat více než jednu funkcionalitu. Navíc je možné používat je opakovaně, pokud chceme
dosáhnout znásobení stejné funkcionality. Díky tomuto přístupu spotřebováváme systémové prostředky
jenom v okamžiku, kdy je to nezbytně nutné. Stinnou stránkou tohoto vzoru ale je relativně vysoká
komplexnost, která mimo jiné ztěžuje například debugování. Navíc je nutné dávat pozor na chyby, které
mohou vzniknout při určování identičnosti a ekvivalence objektů, protože objekt s dekorátorem není shodný
s objektem bez dekorátoru, ač mohou být jejich vnitřní stavy a proměnné stejné.
Facade
Poskytuje unifikované rozhraní skupině rozhraní nebo podsystému, které zjednodušuje jeho používání.
Po tomto vzoru sáhneme, pokud nastane některá z těchto situací:
• podsystém je složitý, ale my mu chceme přiřadit rozhraní, které bude snadno čitelné a neměnné
• existuje příliš mnoho vazeb mezi klientem a třídami podsystému, které znamenají přílišné propojení
25
klienta se systémem a tím pádem špatnou přenositelnost
• chceme používat vrstvy, které spolu budou komunikovat přes jasně dané rozhraní.
Tento vzor je implementačně velice jednoduchý. Třída fasády implementuje rozhraní požadované
klientem, požadavky obdržené voláním metod potom předává dál jednotlivým částem podsystému, které je
dále zpracují. Obdržené výsledky zpracuje tak, aby byl výsledný výstup pro klienta čitelný.
Výstupem je krom výše uvedených důsledků i snížení provázanosti v rámci systému, což kromě zvýšení
přehlednosti znamená i to, že po případných úpravách uvnitř podsystému musí dojít pouze k úpravě kódu
fasády, nikam jinam se změny nepropagují.
Flyweight
Používá sdílení k zajištění vysoké granularity a efektivity při používání většího množství objektů. Protože
prospěšnost tohoto vzoru velmi závisí na kontextu, ve kterém je použit, je nutné používat tento vzor jen
pokud jsou splněny následující podmínky:
• aplikace používá velké množství objektů
• ukládání objektů je spojeno s velkou režií, která je dána právě kvantitou objektů
• většina stavů objektů jsou vnější, tj. lze je reprezentovat vně objektu
• velké množství skupin objektů lze nahradit malým množstvím sdílených objektů v momentě, kdy
odstraníme stavy reprezentovatelné mimo objekt
• aplikace není závislá na identičnosti objektů.
Jádro tohoto vzoru tvoří továrna, která má na starost vytváření a správné sdílení objektů „muší váhy“.
Pokud přijde továrně žádost o objekt, nejdříve zkontroluje fond, kde jsou všechny doposud vytvořené sdílené
objekty uloženy. V případě, že objekt nenalezne, vytvoří nový a uloží ho do fondu. Nakonec odkaz předá
klientovi. Metody sdílených objektů jsou určeny abstraktním objektem „muší váhy“.
Tento vzor s sebou přináší zvýšené nároky na výpočetní kapacitu pro přenos, vyhledávání nebo výpočet
vnějších stavů, což je ovšem vyváženo snížením nároků na paměť. Míra snížení paměťových nároků je dána
mnoha faktory jako počet objektů, množství možných stavů apod.
Proxy
Poskytuje zástupce pro další objekt a řídí přístup k němu. Používá se pokaždé, když potřebujeme chytřejší
způsob odkazování než jen obyčejnou referenci nebo ukazatel. Zpravidla zastupuje objekty, které splňují
některou z těchto vlastností:
• objekt nacházející se v jiném adresním prostoru (vzdálená proxy)
• vzdálený objekt, který není k dispozici na počítači, kde program běží (virtuální proxy)
• velký objekt, který je náročný na vytvoření a udržování (virtuální proxy)
• chráněný objekt, kterému potřebujeme různá přístupová práva pro různé klienty (ochranná proxy)
• zamykatelný objekt, ke kterému smí najednou přistupovat pouze jeden klient (ochranná proxy).
Objekt i zástupce dědí od abstraktní třídy, která určuje rozhraní zastupovaného objektu. Zástupný objekt
zpracovává příkazy od klienta a pak je určí, zda je zastupovanému objektu předat nebo ne. Není možné volat
přímo metody zastupovaného objektu.
Vzdálená proxy umožňuje předávat požadavky na objekty z jiných adresních prostorů, aniž by o tom
klient věděl. Virtuální proxy odkládá načtení velkého objektu do paměti, dokud není jeho instanciace
nezbytně nutná. Ochranné proxy ověřují, zda má daný klient právo v danou chvíli nakládat s objektem.
26
Behavioral patterns
Pracují s algoritmy a přiřazováním zodpovědností objektům. Popisují nejenom samotné třídy a objekty,
ale také komunikaci mezi nimi, poskytují řešení správné kontroly toku. Pokud pracují pouze s třídami,
používají dědičnosti, pokud s objekty, zpravidla přichází ke slovu kompozice.
Chain of responsibility
Zabraňuje příliš těsné vazbě mezi odesílatelem požadavku a jeho příjemcem tím, že dává možnost
zpracování tohoto příkazu většímu množství objektů. Příjemci jsou zřetězeni a předávají si zprávu tak
dlouho, dokud ji některý článek řetězu nezpracuje. Řetěz odpovědnosti je vhodné použít v momentě, kdy:
• více než jen objekt může zpracovávat požadavek, ale předem není známo, který objekt to nakonec bude
• chceme zasílat požadavky jednomu z několika objektů, ale bez konkrétní specifikace příjemce
• množina objektů, která zpracovává požadavky, by měla být specifikována dynamicky.
Skládá se z abstraktní třídy obsluhovače, která definuje rozhraní zpracovávání událostí. Dále
ze samotných obsluhovačů, které definují konkrétní reakce na události a také podmínky, za kterých událost
předají následujícímu prvku v řetězu. Existují dvě implementační varianty: v první je v každém obsluhovači
odkaz na následující prvek v řetězu, druhá k určení následnosti používá externí hierarchii.
Velkou výhodou tohoto vzoru je snížení provázanosti, protože odesílatel ani příjemce o sobě nemusí
přímo vědět, stejně tak jako řetěz nemusí znát svoji strukturu. Ze samé podstaty vzoru také plyne větší
flexibilita, protože jednotlivé příjemce je možno z řetězu odebírat nebo do něj naopak přidávat za běhu
aplikace. Je ale důležité uvědomit si, že jelikož je příjemce žádosti nespecifikován, v rámci řetězu vůbec
nemusí dojít k jejímu zpracování.
Command
Obaluje žádost do podoby objektu, čímž umožňuje zasílání různých příkazů pouze změnou parametru,
žurnálování a používání front žádostí, stejně jako podporu stornovatelných operací. Použijeme ho, pokud
chceme:
• pracovat s voláními, které se provedou až po určité době
• vytvářet, řadit do fronty a vykonávat požadavky v různých časech
• používat funkci obnovení stavu před provedení volané metody undo/redo
• pracovat s logováním operací
•sestavit systém s vysoko-úrovňovými operacemi nad systémem s nízko-úrovňovými operacemi; takové
systémy často používají transakce.
Vzor příkaz se skládá z třídy příkazu, který definuje abstraktní metody vykonání operace. Konkrétní
příkazy dědí od této třídy a překrýváním zmíněných metod dodávají konkrétní funkcionalitu. Příjemce
vykonává operace určené příkazem, třída vyvolávače určuje, v jaký moment bude operace provedena.
V případě, že požadujeme podporu undo/redo, je nutné ukládat kopie příkazů do seznamu a zajistit, aby si
příkaz pamatoval, jak a za jakých okolností byl spuštěn (toto se zpravidla bude velmi lišit program
od programu).
Příkaz zavádí volnější vazbu mezi objekty vyvolávajícími a vykonávajícími operaci. Navíc, jelikož je
příkaz plnohodnotný objekt, můžeme jej rozšiřovat děděním nebo jej skládat do složitějších příkazů či maker
pomocí vzoru Composite. Proto je relativně snadné přidávat nové příkazy, protože není nutné upravovat kód
příjemce příkazu.
27
Interpreter
Při daném jazyku definuje reprezentaci jeho gramatiky současně s tlumočníkem, který tuto reprezentaci
používá k překladu vět v tomto jazyce. Tento vzor se použije v případě, že se v programu vyskytuje jazyk,
který je třeba interpretovat, a zároveň se výrazy v něm dají vyjádřit v podobě stromů abstraktní gramatiky.
Tlumočník pak nejlépe pracuje za těchto podmínek:
• gramatika je jednoduchá; v případě složitých gramatik příliš narůstá množství tříd v hierarchii
reprezentující gramatiku a stává se těžko spravovatelnou
• efektivita nemá nejvyšší prioritu; syntaktický strom zpravidla není nejefektivnějším přístupem, použitím
stavových automatů se obyčejně dosahuje lepších výsledků.
Tento vzor pracuje s třídou abstraktního výrazu, který definuje abstraktní metody společné všem uzlům
abstraktního stromu. Od toho pak dědí terminální a neterminální výrazy, které určují konkrétní chování.
Syntaktický strom je potom sestaven klientem na základě kontextu.
Důsledkem tohoto vzoru je snadná změna či rozšiřování gramatiky, zároveň je celá gramatika relativně
jednoduchá. Co se týče implementace, také je jednodušší přidat nový způsob interpretace gramatiky.
Nevýhodou je bezpochyby to, že rozsáhlejší gramatiky je obtížné spravovat.
Iterator
Poskytuje nástroj sekvenčního přístupu k prvkům agregovaného objektu bez odkrytí jeho vnitřní
reprezentace. Jeho použití je vhodné v těchto případech:
• k zajištění přístupu k agregovanému objektu tak, aby jeho vnitřní reprezentace zůstala klientovi skryta
• k podpoře vícenásobného průchodu agregovanými objekty
• k poskytnutí uniformního rozhraní pro procházení různých agregovaných struktur (to znamená
k podpoře polymorfní iterace).
Jádro vzoru tvoří třídy agregátu a iterátoru, jejichž abstraktní metody určují rozhraní jejich potomků.
Iterátory pak definují konkrétní metody pro procházení agregátu, agregát definuje metodu, která vytváří
instanci iterátoru pro daný typ agregátu. Procházení může být kontrolováno buď iterátorem, nebo klientem,
samotný iterační algoritmus může být obsažen stejně dobře v iterátoru jako v agregátu.
Díky iterátoru můžeme volit různé způsoby průchodu komplexních agregovaných objektů, zároveň ale
máme přehled o tom, jaká pravidla tento konkrétní průchod splňuje. Také není problém, aby s jedním
agregátem pracovalo více iterátorů, které se navzájem nijak neovlivňují. V neposlední řadě dochází
ke zjednodušení rozhraní agregovaného objektu.
Mediator
Definuje objekt, který obaluje skupinu objektů a interakce mezi nimi. Mediátor vynucuje snížení
provázanosti odstraněním explicitních referencí mezi objekty této skupiny a umožňuje jejich interakce
nezávisle měnit. Můžeme ho použít, pokud:
• množina objektů spolu komunikuje jasně definovaným, ale přesto komplexním způsobem, a výsledné
závislosti jsou nestrukturované a těžko pochopitelné
• chceme zvýšit znovupoužitelnost objektů, které to nyní kvůli referencím na okolní objekty a komunikaci
s nimi neumožňují
• potřebujeme chování, které bude rozvržené mezi několik tříd a které bude snadno upravitelné
bez rozsáhlejšího použití dědičnosti.
Tento vzor pracuje s třídami mediátorů a kolegů, jejichž rozhraní opět určuje rodičovská třída
s abstraktními metodami. Mediátor obsahuje reference na všechny kolegy, jejichž komunikaci řídí. Každý
z kolegů obsahuje referenci pouze na mediátora a s ostatními kolegy komunikuje přes něj.
28
Použití tohoto vzoru s sebou přináší významné omezení počtu tříd, neboť nové chování vyžaduje často
pouze nového potomka mediátora a ne změnu všech objektů ve skupině. Dále zmenšuje množství
komunikačních kanálů z M:N na 1:N a přináší abstrakci komunikace objektů. Tím zvyšuje pochopitelnost
a přináší centralizovanou kontrolu.
Memento
Bez narušení zapouzdření zjistí a uloží vnitřní stav objektu tak, aby bylo možné objekt navrátit
do vnitřního stavu později. Používá se, pokud platí obě následující podmínky:
• chceme ukládat vnitřní stav objektu
• použití rozhraní, které by umožňovalo přímý přístup by narušilo zapouzdření a nežádoucím způsobem
by odhalovalo vnitřní strukturu objektu.
Skládá se ze správce, mementa a původce. Memento je objekt, který ukládá vnitřní stav původce, což je
objekt, jehož stav chceme uložit pro pozdější použití. Tento má plný přístup k datům uloženým uvnitř
mementa. Správce je objekt, který si vyžádá memento od původce, ale nikdy nepracuje nad jeho daty,
nanejvýše smí memento předat jinému objektu.
Memento zachovává princip zapouzdření a zjednodušuje původce, protože veškerá logika spojená se
správou uložených stavů je ponechaná na klientovi a správci. Nicméně použití tohoto vzoru může být
paměťově náročné, pokud se ukládá větší objem dat, navíc sám správce neví, jak velkou část objektu je
v mementu uložena a tudíž je obtížně zjistitelné, jak velké paměťové nároky klade na paměť.
Observer
Definuje závislost 1:N takovou, že pokud se změní stav objektu, všem objektům na něm závisejícím je
o tom předána informace. Lze ho aplikovat v libovolném z následujících situací:
• abstrakce má více aspektů, na sobě navzájem závislých, které chceme zapouzdřit do samostatných
objektů, abychom zvýšili znovupoužitelnost (příkladem mohou být dvě grafické reprezentace nad jedněmi
daty)
• změna jednoho objektu vyžaduje změnu ostatních, přičemž nevíme, kolik těchto objektů je
• objekt by měl být schopen zpravit ostatní objekty bez znalosti toho, o jaké konkrétní objekty se jedná.
Vzor se skládá z pozorovatele a subjektu, oba mají opět rozhraní určena rodičovskými třídami a jejich
abstraktními metodami, které překrývají. Subjekt udržuje reference na všechny pozorovatele, poskytuje
rozhraní na jejich přidávání a odstraňování, v případě změny vnitřního stavu umí všechny pozorovatele
informovat. Pozorovatel zpracovává zprávy o změnách stavu, může se jednat o prosté vyvolání metody bez
parametrů. V případě, že je pozorovatel zaregistrován u více subjektů, je vhodné parametricky určit objekt,
ze kterého zpráva přišla.
Pozorovatel přináší volnou vazbu mezi pozorovatelem a subjektem, podporu plošného posílání zpráv,
protože jednou notifikací jsme schopni vyvolat reakci v neomezeném množství objektů. Je ovšem důležité
uvědomit si, že při častých změnách subjektu a velkém počtu pozorovatelů může být použití tohoto vzoru
výpočetně náročné.
State
Dovoluje objektu měnit chování při změně jeho interního stavu. Objekt budí dojem, že se změnila jeho
třída. Použití tohoto vzoru se doporučuje, pokud platí následující:
• chování objektu závisí na jeho vnitřním stavu, jeho chování se musí měnit za běhu v závislosti na tomto
stavu
• metody obsahují rozsáhlé systémy podmínek pracující se stavem objektu, které se v kódu často opakují;
tento stav je většinou reprezentován jedním či více výčtovými typy.
29
Vzor pracuje s třídou kontextu, která reprezentuje objekt nabývající různé stavy, ty jsou potom
definovány třídami konkrétních stavů, které dědí od svého abstraktního předka, který určuje jejich rozhraní.
Každý tento konkrétní stav pak definuje chování, které danému stavu přísluší. Podmínky pro přechody mezi
stavy mohou být definovány jak v kontextu, tak ve stavech samotných.
Přínosem tohoto vzoru je jasné určení, jaké chování je ovlivněno změnou stavu a jak přesně se bude
v daném stavu chovat. Zároveň je stav čitelnější než v případě použití vnitřní proměnné. Tyto stavy navíc
mohou být bez problémů sdílené mezi objekty, čímž se zvyšuje znovupoužitelnost kódu.
Strategy
Definuje rodinu algoritmů, zapouzdřuje je a umožňuje jejich zaměnitelnost. Algoritmus se tedy pak liší
od klienta ke klientovi. Použijeme ho v těchto případech:
• pracujeme s množstvím tříd, které se liší pouze svým chováním
• chceme pracovat s různými variantami algoritmu plnícího stejnou úlohu
• algoritmus pracuje s daty, která nemají být přístupná klientovi
• třída definuje mnoho způsobů chování, z nichž je vybíráno složitým systémem vnořených podmínek.
Vzor se skládá z abstraktní třídy strategie, která definuje rozhraní pro všechny podporované algoritmy.
Od té potom dědí konkrétní strategie, kde je implementován samotný algoritmus. Tyto objekty se potom
použijí k nastavování chování kontextu. Ten může definovat rozhraní, které umožňuje strategiím přistupovat
k jeho datům.
Po použití tohoto vzoru získáme rodiny souvisejících algoritmů, což zvyšuje přehlednost kódu. Zároveň
získáváme flexibilnější variantu k úpravě funkcionality děděním, zároveň nepoužívají složité větvení
podmínek. Nevýhodou je navýšení počtu objektů a režie spojené s komunikací mezi objekty.
Template Method
Definuje kostru algoritmu v operaci, ale implementaci některých jejích kroků ponechává na svých
potomcích. Ti tak mohou měnit měnit tyto kroky a tak i podstatu algoritmu bez změny jeho struktury. Jeho
použití se doporučuje, když:
• je výhodné definovat neměnné části algoritmu v rodičovské třídě a definici proměnných částí ponechat
na potomcích
• potomci některé rodičovské třídy vykazují podobné chování
• vyžadujeme kontrolu nad potomky; použitím šablonové metody dáváme možnost změny chování
potomků jen v přesně určených místech.
Abstraktní třída obsahuje šablonovou metodu, která je stejná pro všechny potomky, a dílčí operace, které
jsou v potomcích různě implementovány a způsobují tak rozdílné chování operace.
Hlavní síla tohoto vzoru je v zajištění znovupoužitelnosti kódu, kterou s sebou přináší. Většinou se
uplatňuje v knihovních metodách. Poskytuje také inverzi řízení, protože volání metod potomků určuje jejich
rodičovská třída.
Visitor
Představuje operaci, která má být vykonána na částech datové struktury. Umožňuje definování nové
operace bez úpravy tříd, se kterými pracuje. Jinými slovy se jedná o oddělení algoritmu od struktury, se
kterou pracuje. Používá se, pokud:
• datová struktura obsahuje třídy objektů s odlišnými rozhraními a na těchto objektech chceme provádět
operace
30
• nad objekty ve struktuře objektu je nutné vykonávat množství rozdílných operací, které v průběhu času
přibývají, toto ale nechceme řešit připisováním nových metod
• struktura objektu se málo mění, ale potřeba nových operací nad nimi je celkem častá.
Skládá se z návštěvníků, kteří implementují operace definované jejich rodičovským rozhraním. Zajišťují
prostředí pro běh daného algoritmu a ukládají jeho stavy. Stejný vztah je u elementu, který definuje
abstraktní metodu příjmu návštěvníka, a jeho potomci ji implementují. Každý element navíc poskytuje
návštěvníkovi rozhraní, přes které může přistupovat k jeho datům. Poslední částí je datová struktura, která
agreguje elementy, případně poskytuje rozhraní vyšší úrovně pro přístup návštěvníků ke všem jeho
elementům.
Díky tomuto vzoru je přidávání nových operací velice snadné. Navíc sdružuje související operace
a odděluje ty nesouvisející, které jsou uzavřeny v třídách návštěvníků. Každý návštěvník může nést vnitřní
stav, protože může navštívit jakýkoli element struktury. Nicméně je obtížné přidávat nové elementy, protože
každý návštěvník musí mít oddělenou metodu pro každý element zvlášť a tudíž přidání vyústí v napsání více
kódu. Také může porušit zapouzdření, protože aby mohl návštěvník s elementy správně fungovat, potřebuje
dostatečně silné rozhraní.
Analýza evaluačních metod a metrik
V data miningu je evaluace velice důležitý pojem, bez kterého se prakticky nelze obejít. Ačkoli je
používán ve více kontextech, většinou se slovem evaluace myslí hodnocení modelů. Většinou se provádí až
na hotových modelech. Slouží k tomu, abychom byli vůbec schopni určit stupeň vhodnosti používání daného
algoritmu. Používá se jednak k tomu, abychom měli představu, jak dobře bude model fungovat
v budoucnosti, pak také jako nedílná součást tvorby modelů. Běžným postupem je vytvořit více modelů
s odlišnými parametry a z nich vybrat ten nejvhodnější právě aplikací evaluačních metrik.
Výstupem evaluace je vždy množina metrik, která popisuje soubor použitých algoritmů. Jelikož jsou ale
tyto algoritmy často velice odlišné a mohou pracovat s rozdílnými typy dat, je těchto metod více a jen
minimum z nich se dá použít univerzálně. Které metody to jsou bude diskutováno v popisech jednotlivých
metod.
Evaluace se samozřejmě nedělí jen podle metrik, které používáme. Další aspektem, který je mnohdy
důležitější než výběr konkrétní metriky, je určení, oproti čemu bude účinnost klasifikačních metod
hodnocena, jaká data budou určena jako trénovací a jaká data budou testovací. V případě, že bychom data
trénovali a testovali na stejné množině, byly by výsledky vychýleny. V tento moment se projeví princip
optimismu, kdy metoda ověřovaná na stejných datech, nad kterými byla postavena, má v reálu horší
výkonost. Plyne to z toho, že metoda dosahující nejlepších výsledků při trénování musí nutně dosáhnout
nejlepších i při testování a tudíž má test nulovou vypovídací hodnotu. Tak se snadno může stát, že jsme
vybrali sice podle výsledků nejlepší, ale ve skutečnosti špatnou metodu, která je pouze extrémně
přizpůsobena konkrétním datům. V takovém případě metodu nazýváme přeučenou, nebo také metodu
s vysokým stupněm zaujetí. Přeučení v tomto případě znamená, že je metoda až příliš přizpůsobená
konkrétním datům a je velká pravděpodobnost, že na jiných datech bude neefektivní. Proto se používají
různé postupy, jak odhalit přeučené metody tím, že na trénování a testování se použijí jiná data. Tyto data
spolu samozřejmě musí souviset a musí pocházet ze stejného zdroje. Data, která by se týkala stejné
problematiky, ale byla by získávána různými způsoby, se mohou lišit ve významu atributů.[7]
Níže uvedené systémy pracují především s metrikou chybovosti modelu.
Hold-out
Data, která máme k dispozici, si rozdělíme na dvě skupiny, z nichž jedna je použita pro testování a druhá
pro trénování. Čím větší je množství dat v trénovací skupině, tím přesnější je potom klasifikační metoda,
nicméně menší množství dat testovacích znamená, že hodnocení modelu je více náchylné k chybě a musíme
uvažovat velkou toleranci získaných hodnot. Opačný stav vede k tomu, že hodnocení modelu má velkou
přesnost, ale klasifikační model má horší pravděpodonost správného natrénování a jeho očekávaná chyba je
31
větší. Obvyklé je používat poměr 70:30, kdy 70% dat určíme jako trénovací a zbytek jako testovací.
Výhodou tohoto systému je zejména jeho rychlost, stinnou stránkou je pak nebezpečí špatně zvolených
testovacích dat. Pokud náhodou vybereme chybně a testovací data budou mít extrémní hodnoty, budou
ve shluku či budou jinak nestandardní, je takto získané ohodnocení modelu prakticky nepoužitelné. Použití
tohoto systému se příliš nevyplácí, je možné ho použít jako doplňkový, pokud se nám podaří dodatečně
získat další data, která již nemohou být použita v procesu. Jinak je pro svojí nepřesnost a malou flexibilitu
prakticky nevyužitelný.
Tento systém se ale často používá v jednom konkrétním případě. Společnosti, které disponují bohatými
datovými zdroji, si nechávají vyhotovit klasifikační problémy externě a chtějí si jejich správnost následně
ověřit. Data jsou proto rozdělena do dvou skupin. Jedna skupina dat je poskytnuta vyhotoviteli, který na něm
postaví své klasifikační metody. Po odevzdání výsledného modelu zadavateli pak tento provede ověření
správnosti modelu na druhé skupině dat, kterou si ponechal.[7]
K-fold křížová validace
Systém křížové validace je asi nejčastěji používaný. Počítá s tím, že máme relativně velké množství dat.
Fold je v tomto případě náhodně vybraná podmnožina dat, kdy všechny foldy jsou stejně velké. Jejich počet
je pak určen číslem k, které zvolí uživatel. Po vytvoření foldů se pak postupuje v cyklech, kdy se jeden
z foldů použije k testování a zbytek dat je použit k trénování modelu. Tento cyklus se opakuje k-krát. Získané
metriky se potom zprůměrují a takto získáváme konečný výstup. Ten velice dobře odráží to, jak se daný
model bude chovat v budoucnosti na doposud neznámých datech.
Výhodou křížové validace je její flexibilita. Podle množství foldů, které si nastavíme, můžeme snadno
ovlivňovat rychlost a přesnost. Čím více foldů, tím větší je přesnost, protože eliminujeme pravděpodobnost
většího vlivu náhodných skupin nestandardních dat. Samozřejmě větší množství foldů znamená i delší
výpočetní doba, protože tolikrát se musí procházet všechna data. V praxi je běžné používání deseti foldů, kdy
je již dostatečně velká přesnost, zároveň se jedná o rozumně rychlou variantu. Nedoporučuje se používat
hodnoty menší než 5, protože výsledky jsou příliš zkreslené.
Křížová validace se ještě používá ve specifické variantě stratifikované křížové validace. V této metodě se
zohledňuje to, že na modelu se projeví i rozložení výstupů napříč použitými daty. Toto je důležité zejména
u klasifikace a regrese. Pokud by se totiž stalo, že některé foldy obsahují jen výstupy jednoho typu
(u klasifikace), či hodnoty jen v jedné části intervalu výstupů (u regrese), zavádíme tak do modelu výchylku.
Toto se odstraňuje stratifikací, kdy se v každém foldu snažíme dodržet stejné rozložení výstupů, jako je tomu
u celé množiny dat. U klasifikace se snažíme zachovat stejný poměr zastoupení jednotlivých tříd, u regrese
se pak řídíme střední hodnotou výstupů.[7]
Leave-one-out
Tento přístup je vlastně variantou křížové validace, kde počet foldů k je shodný s počtem instancí.
Dochází tedy k tomu, že trénování modelu probíhá vždy na celé množině s vynecháním pouze jediné
instance. Tato metoda se používá v případech, kdy máme k dispozici pouze omezené množství dat (obvykle
se uvádí méně jak sto instancí).
Výhodou je velká přesnost evaluace. Nevýhodou je výpočetní náročnost vzhledem k počtu cyklů, kterými
se v rámci tohoto systému prochází a nízká flexibilita.[7]
Validace opakovaným vytvářením náhodných vzorků
Další blízký příbuzný křížové validace. Jedná se o systém, který pro testovací a trénovací data používá
náhodně vybraných podmnožin dat, přičemž je pouze dodržována zásada, že množina trénovacích dat je
vždy větší než množina dat testovacích. Výhoda oproti křížové validaci je v tom, že neexistuje vztah mezi
velikostí podmnožin a počtem opakování.
Tento systém se v oblasti data miningu příliš nepoužívá. Ač je velice flexibilní, jeho problémem je
32
neopakovatelnost, která plyne z náhodnosti vzorků. Také zapříčiňuje, že nemáme záruku, že se nám
v různých cyklech nebudou opakovat stejná instance v testovacích. Tím se můžeme dostat do stejných
problémů, jaké jsou u systému hold-out, pokud opakovaně do testovacích dat zařadíme instance
s extrémními hodnotami. Tomu se sice můžeme vyhnout použitím stratifikace podobně jako u křížové
validace, tím ale narážíme na problém. Protože v každém kroku cyklu se volí vzorek dat náhodně, není
možné si předem rozdělit množinu dat tak, aby se zajistila ve všech krocích. Tím pádem by bylo třeba
vybrané vzorky upravovat před každým trénováním tak, aby si stratifikačně odpovídali, což by výrazně
zvedlo výpočetní náročnost.[15]
Bootstrap
Tento systém se někdy uvádí pod jménem Bootstrap 0.632. Používá se v situacích, kdy je k dispozici
extrémně malé množství dat, obvykle se uvádí pod padesát instancí. Systém spočívá v tom, že vždy
v jednom kroku cyklu rozdělíme data na dvě části, na trénování se použije ta o velikosti hruba dvou třetin.
Oproti výše zmíneným metodám ale tentokrát ohodnotíme model jak na testovacích, tak na trénovacích
datech, přičemž výsledná hodnota je dána rovnicí:
e=0.632∗e train0.368∗e test
Tento postup opakujeme tolikrát, kolik instancí máme. Výsledek je průměr hodnot.
Bootstrap se používá prakticky výhradně v případech, kdy máme k dispozici malé množství dat, kdy má
oproti ostatním výhodu vyšší přesnosti. Při větším počtu instancí nemá oproti ostatním přístupům žádné
výhody – je výpočetně náročný, není flexibilní a neposkytuje výrazně větší přesnost.[7]
Metriky
V následujících odstavcích jsou posány metriky, které se používají k ohodnocování modelů v data
miningu. Uvedl jsem i metriky, které sice neslouží přímo k hodnocení modelu, ale ostatní metriky se o jejich
hodnoty mohou opírat.
Chyba
Chyba modelu je základní statistika, která se používá na určení správnosti modelu. Je to numerická
hodnota, která určuje rozdíl mezi skutečnou hodnotou atributu, které klasifikujeme a jeho predikovanou
hodnotou. Chyba modelu se uvádí vždy jako průměr chyb jednotlivých klasifikací. Jsou celkem 3 způsoby
výpočtu chyb, z nichž je nejpoužívanější ta poslední: běžná, absolutní a kvadratická.
m
1
Err = ∑  y i − y 'i
m i=1
m
Err ab =
1
∑ ∣y − y '∣
m i=1 i i
Err sq=
1
 yi − y 'i 2
∑
m i=1
m
Chybu lze potom potom rozdělit podle toho, na jakých datech ji počítáme. Chyba trénovací je taková
chyba, kterou model vykazuje na těch datech, na kterých byl vytvořen. Chyba testovací se zjišťuje na datech,
u kterých známe hodnoty výstupů, ale které jsme nepoužili pro trénování. Chyba reálná je potom chyba,
kterou bude model vykazovat na všech datech, které mu předložíme. Tuto chybu samozřejmě neznáme,
ale snažíme se jí co nejlépe přiblížit.
Zaujetí
Zaujetí nebo anglicky bias je metrika, která nám říká, jak moc se očekávaná hodnota modelu (ta je rovna
33
průměru ze všech možných hodnot, kterých může nabývat vynásobených jejich váhou) liší od skutečné
hodnoty parametru. Skutečná hodnota je v tomto kontextu uvažovaná ze všech možných hodnot, ne pouze
z množin dat, kterou disponujeme.

Bias=E  −
 zde potom je očekávaná hodnota modelu a  je pak skutečná hodnota.
E  
Variance
Variance je hodnota, která udává, jaká je míra rozptylu, průměr druhé mocniny možných hodnot modelu
k očekávaným hodnotám.
Var  X =E [− E 2 ]
Matice záměn
predikovaná
hodnota
reálná hodnota
třída A
třída B
třída C
celkem
třída A
3
5
8
16
třída B
7
4
6
17
3
13
4
13
20
34
27
třída C
celkem
Tabulka 1: matice záměn pro tři třídy
Matice záměn je metrika, která se používá výhradně u klasifikace. Je to čtvercová matice, jejíž velikost je
dána počtem tříd, do kterých klasifikujeme. Řádky představují třídy, které jsme klasifikovali pomocí našeho
modelu, sloupce jsou potom reálné hodnoty. Hodnoty, které jsou na jednotlivých pozicích matice, potom
představují, kolik příslušníků třídy sloupce bylo ve skutečnosti klasifikováno jako příslušníci třídy řádku.
(tabulka č.1)
Evaluace klasifikace
Pod tímto pojmem jsou myšleny metriky, které se vztahují ke klasifikaci. Ta klasifikuje hodnoty do
jednoho ze dvou možných stavů, které se označují jako pozitivní a negativní. Tyto metriky lze samozřejmě
použít i v případě klasifikace do více tříd, nicméně se posuzuje každý model zvlášť, kdy pozitivní stav
znamená příslušnost k dané třídě. Patří sem následující metriky:
•
TPr, true positive rate - určuje, kolik instancí do třídy patřící bylo správně klasifikovaných, také
bývá označována jako citlivost nebo recall
•
TNr, true negative rate - určuje, kolik instancí do třídy nepatřící bylo správně klasifikovaných,
bývá též označována jako specificita
•
FPr, false postive rate - určuje, kolik instancí do třídy nepatřící bylo špatně klasifikovaných jako
patřící do třídy
•
FNr, false negative rate - určuje, kolik instancí do třídy patřící bylo špatně klasifikovaných jako
nepatřící do třídy
•
Pre, precision - určuje, kolik instancí, klasifikovaných jako do třídy patřící do třídy patřilo
i ve skutečnosti
•
F-1 measure – je kombinace výše uvedených metrik, která se používá k identifikaci takového
nastavení, které je vhodným kompromisem mezi výše uvedenými metrikami
34
F1=
2∗Pre∗TPr
PreTPr
Z těchto hodnot lze potom dopočítávat další metriky. Například je vidět, že chybu modelu spočítáme tak,
že sečteme falešně negativní a falešně pozitivní klasifikace a ty potom podělíme celkovým počtem tříd. [6]
Matice cen
Matice cen je metrika, která není výsledkem evaluace modelů. Často se s ní můžeme setkat, protože
mnohé metriky ji mohou zohledňovat ve svých výpočtech za předpokladu, že je definovaná. Tato matice
ovlivňuje i samotné trénování modelu. Říká, jakou třídu by měl model preferovat v případě, že se rozhoduje
mezi více variantami. Tuto metriku nelze nijak vypočítat či odvodit přímo z dat, většinou ji vytvářejí
doménoví experti, kteří znají přesný význam dat a jejich klasifikace.
Tato matice vypadá na první pohled stejně, jako matice záměn, ale význam čísel se významně liší. Číslo
na souřadnicích (A,B) nám totiž říká, jaká je cena klasifikace do třídy A v případě, že je instance
ve skutečnosti příslušníkem třídy B. Platí zásada, že klasifikace do správné třídy má nulovou cenu, jednotlivé
ceny pak bývá zvykem uvádět v celých číslech, které se zpravidla pohybují od jedné do deseti.
predikovaná
hodnota
třída A
třída B
třída C
celkem
třída A
0
1
2
3
třída B
5
0
1
6
třída C
celkem
10
15
5
6
0
3
15
Tabulka 2: matice cen pro tři generické třídy
V tomto příkladě (tabulka č.2) je ilustrováno, jak může matice cen vypadat. Zde jasně vidíme, že je pro
nás výhodnější chybovat tím, že nesprávně označíme instanci jako patřící do třídy A, než chybně prohlásit
instanci za příslušníka třídy C. Konkrétně by se mohlo jednat o například o klasifikaci na základě lékařských
dat, která má zjistit, zda je pacient nemocen. Třída A by pak znamenala pokročilé stádium, třída B prvotní
stádium a třída C znamenala, že je pacient zdráv. V případě, že by byla klasifikována přítomnost nemoci
v libovolném stádiu, pacient by byl poslán na další sérii testů, které doporučí další léčbu. Z matice pak lze
odvodit, že náklady za další testování pacienta jsou výrazně menší než náklady spojené s přehlédnutím
nemoci a následnou léčbou.
ROC křivka
ROC křivka, někdy také označována jako hraniční křivka. Je to metrika, která nám popisuje chování
klasifikátoru tím, že zaznamenává změnu citlivosti v závislosti na změně míry falešně negativních výsledků.
Na obrázku (obrázek č.1) můžeme vidět příklad ROC křivky. Rovná čára, která rozděluje graf na dvě
poloviny, představuje klasifikaci náhodným výběrem (z toho plyne její poloha, neboť náhodná klasifikace
má stejnou pravděpodobnost zařazení do třídy pozitivní i negativní). Hranatá křivka potom představuje
zkoumaný klasifikátor. Čím větší je konvexnost této křivky, tím je daný model lepší. Naší snahou totiž je
přiblížit modely co nejvíce souřadnici (0,1), která představuje bod optimálního klasifikátoru.[10]
Průběh ROC křivky získáme tam, že měníme hranici, která představuje rozdíl mezi klasifikací do positive
a negative, která je běžně nastavena na hodnotu 0,5. Jejím posunem oběma směry získáme nové klasifikační
výstupy, jejichž poměr citlivosti a false positive rate nám dává body na ROC.
35
Obrázek 1: ROC křivka klasifikačního modelu
AUC
AUC nebo-li plocha pod křivkou je mírou určování kvality modelu. Získává se tak, že spočítáme velikost
plochy pod křivkou ROC. Čím větší tato plocha je, tím více se blížíme bodu (0,1), který představuje ideální
klasifikátor. V následujícím obrázku (obrátek č. 2) obrázku je přehled, jakou plochu by měl mít výborný,
dobrý či špatný klasifikátor. Tato metrika bývá také označována jako diskriminace, tedy schopnost správně
rozlišovat negativní a pozitivní instance.[11]
Obrázek 2: kvalita klasifikace vyjádřená
metrikou AUC (křivky shora: skvělá, dobrá,
špatná)
Ostatní metriky
Evaluačních metrik je samozřejmě mnohem více, ale jejich použití není příliš časté, už jen proto, že pro
běžného uživatele je jejich význam nejasný. Používání takových metrik v data miningových software se tak
snadno stane kontraproduktivním, protože tyto metriky mohou být neznalou osobou špatně interpretovány.
Příkladem dalších metrik může být Cohenova kappa statistika (míra shody modelu s reálnými hodnotami)
nebo tzv. informační hodnota (angl. information score) dvojice Kononenko & Bratko (hodnotí klasifikátory s
tím, že zohledňuje pravděpodobnostní rozložení jednotlivých tříd).
36
Kapitola 4
Analýza
Základní stavba Fake Game
Konfigurace
Vizualizace
Načítání dat
Preprocessing
GAME
Generování reportů
PMML
Obrázek 3: UML diagram základních modulů Fake Game
Program lze takto rozdělit podle posloupnosti funkcí, které vykonává. Načítáním dat pracuje
s obyčejnými textovými soubory. Pokud v nich najde odpovídající hlavičku v podobě výčtu atributů,
s výstupními atributy opatřenými vykřičníky, nahraje jejich obsah do vnitřních struktur programu.
Preprocessing není nezbytnou součástí zpracování. Mezi jeho nejvýznamnější funkce patří standardizace
hodnot do intervalu <0,1>, která významně zvyšuje přesnost následně generovaných modelů. Jádro Game
vytváří modely na základě konfigurace, která je mu dodána (ať už z externích souborů nebo z grafického
uživatelského rozhraní). Modely pak lze ukládat ve formě PMML souborů a stejně tak je možno je
i nahrávat. Výstupem jsou reporty a vizualizace, které vycházejí jak z původních dat, tak z modelů, které
byly vygenerovány.
Problémy spojené se současnou verzí
Většina problémů tohoto programu je spojená s tím, že byl od začátku vyvíjen systémem ad hoc.
Neexistovala větší koncepce o budoucím obsahu, která by umožňovala návrh programu po větších částech,
na programu navíc spolupracovalo větší množství lidí, přičemž každý měl o funkci programu svojí
představu.
Toto se velmi projevilo na zapouzdření, které v mnohých částech programu prakticky neexistuje.
Příkladem může být původní nastavení viditelnosti proměnných v třídě TreeData, která reprezentuje
množinu instancí, která vstupuje do programu, i s jejich atributy a výstupními daty. Ačkoli hodnoty
některých proměnných jsou přímo závislé na jiných, a tudíž jejich hodnoty musí vždy reflektovat tyto jiné
hodnoty, je přístup k nim nastaven na public. Konkrétně je to například celočíselná hodnota iNumber, která
určuje, kolik vstupních atributů se v nahraných datech nachází a měla by vždy odpovídat velikosti vektoru
iAttr, uživatel ji může měnit z libovolné části programu.
Asi nejzákladnějším problémem je prakticky nulová dokumentace. V novějším úsecích kódu se již začíná
objevovat, ale staré části, které tvoří základní metody, které musí stejně všechny nově napsané moduly
používat, dokumentovány nejsou vůbec.
37
Dalším problémem je, především tedy ve starších částech kódu, oddělení grafické reprezentace a obsahu.
V třídách, které operují s grafickým rozhraním, obsahují kód, ve kterém se provádí výpočty nesouvisející
s GUI a měnící vnitřní stavy programu. Toto je nejmarkantnější na třídě GMDHtree, která měla původně na
starost nejen vykreslování oken, ale také se starala o uchovávání informací o síti, která prováděla trénování
modelů. Poslední vývoj sice vedl k odstranění nejhorší prohrešků, ale stále je co opravovat.
Jedním z nejvýraznějších problémů, který se významně podílí na počtu chyb v nově vznikajících částech,
je celková nejasnost kódu. Proměnné jsou často pojmenované zkratkami, ze kterých není patrné, k čemu by
měly sloužit. V těchto případech navíc není používána velbloudí notace, takže pak se můžeme setkat
například s tím, že metoda getiVal() ve skutečnosti znamená „get input value“ a getStiValue() „get
standardized input value“. Toto je navíc spojeno s absencí dokumentace, takže pro pochopení funkcí metod
je často nutné zdlouhavě procházet kód a přesnou činnost a případná omezení číst přímo něj.
Se všemi výše zmíněnými pak souvisí poslední neduh programu, kterým je redundance. Jelikož je obsah
funkcí špatně čitelný, mnohdy se stává, že je zvolen přístup menšího zla, kdy je raději podmínka ověřována
dvakrát, než aby nebyla ověřena vůbec. Dalším projevem pak je zajišťování kontrolních funkcí mimo
metody, se kterými souvisí, přestože tyto jsou v nich již obsaženy. Toto je typické zejména pro volání metod
jiných balíčků, kde je autorem jiná skupina lidí a proto je zde nízká znalost kódu.
Analýza evaluačních metod ve Fake Game
Cílem tohoto rozboru bylo určit, jaké evaluační metody jsou v této chvíli v programu Fake Game
k dispozici a jak jsou implementovány. Dále jsou metody analyzovány v kontextu správnosti kódu a
použitých návrhových vzorů. Nakonec je určeno, zda je tato metoda vhodná a je možné ji použít
při rozšiřování aplikace, nebo je vhodné ji nahradit jinou metodou. Také je diskutována možnost použití
návrhových vzorů do budoucna.
Ve Fake Game jsou modely uloženy v singleton objektu Models, data pak v singletonu TreeData. Obě
dostupné evaluace vždy hodnotí pouze ty modely, které jsou v singletonu.
Evaluace modelů přes metodu saveToFile()
Program Fake Game dlouhou dobu nepoužíval většinu evaluačních metrik. Prováděla se pouze základní
analýza chyb, která byla počítána v rámci objektu TreeData v metodě saveToFile(). Výsledky této metody
byly potom rozděleny do dvou částí, které se dále zpracovávaly odlišně. První část výpočtů, která je
rozsáhlejší z těchto dvou, je postupně ukládána do řetězce line, na konci výpočtu je pomocí
Obrázek 4: vzorek kódu metody saveToFile() objektu TreeData
38
DataOutputStream zapsána do souboru. Druhá část je zpracovávána do řetězce ret a doplněna o značky, které
umožňují následné parsování. Tento řetězec je potom vracen jako výstupní hodnota metody.
Tento výstup není převážnou většinou metod programu dále zpracováván. Objekt GMHDtree, přes který
je program Fake Game spouštěn a obsahuje velkou část grafického rozhraní, však výstupní řetězec ukládá.
Třída ho ale ve výsledku nijak nevyužije, pouze dojde k jeho zobrazení do dialogového okna, kde je díky
zalomení textu vidět jen malá část. Pravděpodobně jde o chybu.
Jediné místo, kde ke zpracování informací skutečně dojde, jsou objekty TrainTestStrategy
a CrossvalidationStrategy. Jak sám název napovídá, jedná se o objekty, které provádí analýzu modelů
pomocí systémů Hold-Out a k-fold křížové validace, přičemž uvažují metriku chyby. Konkrétně jde o druhou
odmocninu kvadratické chyby a klasifikační chybu. Ta je v tomto případě definována tak, že je rovna nule,
pokud je instance klasifikována správně, nebo rovna jedné, pokud je instance klasifikována špatně.
Z objektového hlediska je tento způsob evaluace modelů velmi nevhodný. Důvodů je hned několik. Jedna
jejich část se týká správnosti implementace ve smyslu GRASP, další z nich přehlednosti kódu a část
náročnosti kódu. V následujícím rozboru uvažujeme jenom ty problémy, které se týkají přímo metody
související s evaluací, tedy metody saveToFile().
fakegame
CrossvalidationStrategy
game.data
+runGAME()
TreeData
+saveToFile()
TrainTestStrategy
další zpracovávání výstupu
metody v těchto třídách
+runGAME()
game.gui
game.cli
FAKEGAME
+FAKEGAME()
+generateGAME()
Controls
+repeatGenerating()
+saveFile()
GMDHtree
+saveMenuActionPerformed()
s výstupem manipuluje,
ale výsledky se ztratí
Obrázek 5: UML diagram tříd, které využívají metodu saveToFile()
Prvním problémem je v třídě TreeData, kde dochází k míchání nesouvisejících oblastí kódu. Primární
úkol této třídy je pracovat s množinou dat, kterou máme k dispozici, a provádět operace s ní související. V
takovém případě ale není úplně správná přítomnost metody, která pracuje s ukládáním a nahráváním
souborů, protože ta přímo nesouvisí se správou instancí. To je nicméně spíše kosmetická záležitost, která by
pomohla zpřehlednění kódu. Důležitější otázkou spíše je, proč metoda, která má primárně na starost ukládání
potomků třídy Model a pracuje prakticky výhradně s jejich daty, je v třídě, která pracuje s datasetem. Ještě
horší je, že v přímo v metodě saveToFile() dochází k práci s grafickým rozhraním, konkrétně jde o vytváření
swingových objektů. To znamená, že tato metoda může být smysluplně volána pouze z GUI. Její použití
kdykoli mimo grafické rozhraní je nespolehlivé a vyžaduje „přiohýbání“ kódu, které přináší zvýšenou
výpočetní náročnost a často do kódu zanáší těžko odhalitelné chyby.
Zbytečnou režii navíc představuje i spojení výpočtu evaluace a ukládání souboru. Zejména v případě
křížové validace je toto markantní, protože vytvářené soubory jsou neustále přepisovány, takže režie se
zápisem do souboru přichází vniveč. Vzhledem k tomu, že křížová validace je používána velice často, je toto
obzvláště nešťastné.
Další chyba je v celkové nejasnosti. Konkrétně se jedná o to, že metoda je sama o sobě velmi dlouhá a její
rozdělení na menší úseky by její jádro výrazně zpřehlednilo. Nicméně toto může být záležitost
39
programátorského vkusu a proto se nejedná o chybu jako takovou. Daleko větším problémem je to, že
v rámci vkládání dat do řetězce dochází k tomu, že se nevkládají přímo hodnoty proměnných, ale dochází
k jejich přepočítávání. Tak je velice obtížné dovtípit se, jaká je skutečná hodnota, která se posílá dál,
a především jaký je její význam. Toto se týká jak ukládání do souboru skrze řetězec line, tak i výstupu
funkce v řetězci ret.
Posledním neduhem je pak fakt, že část chování této metody není určena pouze parametry metody, ale
také proměnnými v rámci TreeData. Konkrétně se jedná o proměnnou usePMML, která určuje, zda se mají
modely uložit i ve formátu PMML, a saveResponses, která znamená ukládání většího množství parametrů.
Tyto proměnné se používají pouze v případě volání saveToFile(), žádný jiný účel nemají. Ač jsou nastaveny
na přístup private, lze je neomezeně nastavovat příslušejícími settery, takže změna může být provedena
odkudkoli. Takto volající bezdůvodně ztrácí kontrolu nad voláním funkce. Pokud se před voláním zapomene
ujistit, že jsou tyto proměnné nastavené tak, jak potřebuje, může se mu chování této metody změnit, aniž by
o tom věděl. Vzhledem k tomu, že TreeData jsou implementována jako singleton, je pravděpodobnost,
že tento stav nastane, značná.
Poslední drobnost je matoucí název tříd CrossvalidationStrategy a TrainTestStrategy. Nejedná se
o aplikaci návrhového vzoru Strategy, jak by se z názvu šlo domnívat, ale o objekty typu Template Method.
Co se týče možného použití dalších návrhových vzorů, tak by zde existovala možnost řešení problémů
s nastavováním vnitřních proměnných tak, že pro ukládání rozšířených dat a PMML souborů by se použil
vzor Dekorator, kdy rozšiřovanou funkčnost by představovalo právě ukládání. Dokud je ale ukládání
zařazeno v TreeData, jsou tyto úvahy zbytečné, protože tento vzor by vyžadoval přesunutí ukládání
do zvláštní třídy.
Použití tohoto způsobu evaluace v dalších verzích programu Fake Game není kvůli počtu chyb v žádném
případě žádoucí. První pokusy s úpravou této metody a jejím částečným oddělením do nové třídy Evaluation,
která by sdružovala veškeré proměnné a metody spojené s evaluací, skončil nezdarem. Zvětšila se tak sice
přehlednost v ohledu umístění proměnných a byly opraveny chyby s nastavením přístupů, nicméně se
nepodařilo vynutit odpovídající rozhraní, přes které by bylo možné k datům přistupovat. Toto se stalo
zejména z toho důvodu, že by toto znamenalo příliš velká změny v okolním kódu, které by byly příliš
zdlouhavé. Případné chyby v převodu volání na nové rozhraní by pak mohly vést i ke skrytému omezení
funkčnosti.
Evaluace modelů pomocí balíčku preprocessing.statistic
Tento modul byl do Fake Game přidán teprve nedávno. Odpovídá na narůstající potřebu použití
sofistikovanějších evaluačních metod než těch, které poskytuje metoda saveToFile(). Staví na sjednoceném
rozhraní, které je definováno v interface StatisticsWorker. To definuje jednoduché metody, které musí
implementující objekty splňovat. Metoda run(TreeData treeData) vrací JPanel, který obsahuje grafické
rozhraní jednotlivých statistických metod. Metoda getName() pak vrací jméno dané metody. Všechny tyto
statistické metody jsou potom zobrazovány v rámci jednotného rozhraní, které je obsaženo v třídě
StatisticsGUI. Jedná se o jednoduchý swingovský objekt dědící od JFrame, jehož jedinou funkcí je
zobrazování objektů, které implementují již zmíněné rozhraní StatisticksWorker. Tyto objekty jsou načítány
za pomoci třídy UnitLoader, která je vytváří na základě textového souboru, kde jsou zapsána jména tříd.
Na UML třídním diagramu (obrázek č. 6) můžeme vidět, které třídy v rámci balíčku používají evaluační
metody. Nicméně výše uvedené třídy nejsou jediné, které dědí od StatisticsWorker, ale ostatní nepracují
s evaluací modelů.
Třída FalsePositiveNegative zobrazuje matici záměn pro jednotlivé třídy a počítá pro ně přesnost
a citlivost. Zároveň umožňuje zobrazení statistik FPr, FNr, TPr, TNr a přesností klasifikace do pozitivních
a negativních. Velice zajímavý rys je slider, kterým lze měnit hraniční hodnotu oddělující klasifikaci
do positive a negative. Se změnou této hraniční hodnoty se potom vytvoří nová statistika. Výpočty tohoto
modulu probíhají v metodě compute(TreePath[] selectedNames). Ta jako vstup bere označenou cestu
stromem, skrz který probíhá výběr (obrázek č.7). Na základě jména, které je v tomto stromě označeno, se
pak provádí výpočty. Výsledky jsou potom v podobě textu zobrazeny přímo do GUI. Metoda sama o sobě
nic nevrací.
40
StatisticsWorker
porovnávání výstupů
+run()
+getName()
StatisticalBlock
StatisticsGUI
zobrazení ROC křivky
ReceiverOperatingStatistics
FalsePositiveNegativeDistribution
FalsePositiveNegative
+display(TreeData)
UnitLoader
distribuce FP a FN
zobrazení matice záměn
+statName
+newInstance()
Obrázek 6: UML diagram tříd, které se v modulu statistics podílí na evaluaci
Třída FalsePositiveNegativeDistribution má na starost vykreslování grafů rozložení míry FN a FP
v závislosti na změně hraniční hodnoty. Používá velice podobné výpočty jako předchozí třída. Jádro jejích
výpočtů opět probíhá v metodě compute(TreePath[] selectedNames) se stejným principem.
Obrázek 7: modul statistického balíčku s maticí záměn a statistikami souvisejících metrik
Třída ReceiverOperatorCharasteristics funguje opět na stejných principech jako předchozí, jen zobrazuje
ROC křivku. Metoda compute(TreePath[] selectedNames) opět obsahuje výpočty.
Poslední třída pracující s evaluací modelů je StatisticalDataProcessor (obrázek č. 8). Jeho obsahem je
výpočet zaujetí a variance (zde označovaných jako systematic error a random error). Je možné porovnávat
model vůči reálným hodnotám, ale také model vůči jinému modelu. V takovém případě samozřejmě musí
platit, že oba modely musí pracovat nad stejnými daty. Další funkcí by mělo být vytváření reportů ve formátu
pdf, možnost volby různých druhů testů atp. V době vytváření této práce nicméně tyto funkce ještě nebyly
zprovozněny. Jádrem výpočtů je metoda compute(), doplňkové metody jsou precompute(),
computeAutomatic() a computeEnsemble(). V těchto výpočtech jsou používány třídy balíčku
preprocessing.statistic.statisicalblock.
Tento statistický balíček je velkým posunem kupředu jak s ohledem na funkčnost, tak s ohledem
na čistotu designovou a implementační. Už jenom nastavení rozhraní společného pro součásti, které patří
do tohoto balíčku, zajistilo výrazně velkou přehlednost kódu. Zároveň jsou související data udržována
v oddělených třídách a obsahují malé množství metod, takže je snadné se v nich zorientovat.
41
Obrázek 8: modul statistického balíčku zobrazující bias a varianci
Nicméně i tak má tato část aplikace své stinné stránky. Opět je zde ten problém, že se dohromady míchá
grafická reprezentace a data. To by byl opět problém kosmetického rázu, kdyby ovšem neexistovala mezi
těmito dvěma částmi silná vazba. Jak je vidět na většině výše uvedených metod, vstupy výpočetních funkcí
jsou objekty z frameworku Swing, čímž je zajištěno, že jakékoli volání těchto metod mimo GUI bude velice
obtížné. Hlavní problém je ale v tom, že v metodách výpočtu jsou výstupy nedosažitelné, neboť se
neukládají do žádných proměnných a pouze se tisknou do grafického rozhraní. To by ještě bylo pochopitelné
u těch částí, kde dochází k vykreslování grafů. Provázanost grafiky a dat by tudíž byla přijatelná, ale
u ostatních částí je to značný nedostatek.
Výše uvedené problémy tak opět přináší nemožnost použití těchto metod v jiném kontextu, jako již
v několikrát zmíněném CLI. Toto by se ale mělo změnit i z toho důvodu, že za aktuálního stavu není možné
provádět testování bez pomoci speciálních software, které umí číst hodnoty z grafických výstupů. Přitom
zrovna v Fake Game je celkem častým jevem to, že změny jádra mají tendenci ovlivňovat externí moduly.
Důvod jejich nefunkčnosti je pak těžko odhalitelný, neboť se chyba zpravidla projeví až s odstupem. Potom
je zapotřebí zpětně dohledávat, která konkrétní změna tuto chybu vyvolala. Tomu by se přitom snadno dalo
zabránit začleněním automatických testů do build manageru Maven, který je v rámci projektu Fake Game
používán.
Z pohledu návrhových vzorů tento balíček nemá nedostatky, je relativně jednoduchý a nucené zavedení
návrhových vzorů by nepřineslo žádná pozitiva, ale pouze zkomplikovalo kód. Samozřejmě by mohla
vyvstát otázka, zda by například po oddělení GUI a výpočtových části nestálo za to změnit na návrhový vzor
Strategy, protože aktuální použití funkce run() na první pohled vypadá obdobně. Zde si je důležité uvědomit,
že tento vzor představuje pouze zapouzdření metody do objektu. Zde ovšem potřebujeme držet informace
o komponentách a tak je tento vzor nepoužitelný.
Evaluace v programu Weka
Evaluace je v programu Weka velice propracovanou částí se kterou se setkáváme pokaždé, když
vytváříme klasifikátory, jelikož je součástí standardního statistického výstupu. Základ tvoří třída Evaluation,
ve které se udržují všechny důležité proměnné a která provádí i výpočty. Jen minimum kalkulací se provádí
mimo vlastní třídu, jedinou výjimkou je v tomto případě výpočet ROC křivky, který probíhá za pomoci třídy
42
TresholdCurve. Při regresních problémech je malá část výpočtů zajišťována třídou KernelEstimator. Všechny
hodnoty jsou uloženy v primitivních datových typech. Opět se ale najde výjimka v podobě matice cen
uložené v objektu CostMatrix.
Weka používá k vytvoření evaluace modelu dvě základní metody, které se liší pouze použitým systémem.
První je evaluateModel(). Do té v parametrech vstupují (mimo jiné) instance třídy Classifier a Instances.
Tato metoda provede ohodnocení modelu na jedné množině dat, což odpovídá systému Hold-Out. Druhá je
pak crossValidateModel(). Ta funguje obdobně, jen je v ní další parametr - počet foldů. Evaluace pak probíhá
křížovou validací. (obrázek č. 9)
KernelEstimator
+getProbability()
Evaluation
CostMatrix
+toSummaryString()
+evaluateModel()
+crossValidateModel()
pouze u regresních
problémů
Classifier
TresholdCurve
Instances
Obrázek 9: třídy spolupracující na evaluaci v programu Weka
Třída Evaluation poskytuje velice širokou nabídku metrik. Přitom využívá toho, že výpočty mnohých
z nich jsou podobné, takže celkový počet výpočtů na jejich získání je snížen pomocí sdílení proměnných
získaných v mezikrocích výpočtu. Nabízené metriky zahrnují matice záměn a metriky s ní související včetně
F1 míry a mnoho druhů chyb, jsou ale nabízené i složitější, jako je kappa statistika nebo information score.
Devizou této třídy je také to, že umožňuje jak ovládání přes GUI, tak přes CLI. Protože i v grafickém
rozhraní je výstup čistě textový, není v příkazové řádce nijak omezena funkcionalita. Přístup přes CLI navíc
předpokládá absolutní izolovanost, takže je možné spouštět evaluační metody bez toho, aby byl zbytek
programu aktivní. Stačí jen do parametrů spuštění zadat soubory, ve kterých jsou uloženy modely a data.
Po návrhové a implementační stránce není tomuto modulu co vytýkat. K metrikám je dokonce možno
přistupovat přímo a ne jen přes výstupní řetězec, takže není problém vybrat jen ty metriky, které jsou pro nás
relevantní. Krom toho je také možno snadno dílčí metriky testovat.
Jediné, co by možná zlepšilo používání evaluace ve Wece, by byla zjednodušená verze Evaluation, která
by obsahovala skutečně jen ty nejzákladnější metriky pro případ, kdy chceme provádět větší množství
rychlých evaluací.
43
Kapitola 5
Návrh & Implementace
Diskuse možných postupů
Při návrhu nového evaluačního modulu máme na výběr celkem ze tří variant:
První je varianta napsání vlastního kódu zcela odděleného od veškerých existujících modulů. Toto se
nevyplatí zejména z toho důvodu, že by to vyžadovalo větší zásah do prostředí Fake Game a celá
implementace by byla výrazně časově náročnější a s větším sklonem k chybám. Dalším nežádoucím
aspektem je to, že by tím došlo k rozdrobení stejné funkcionality do více míst a tím pádem by aplikace
nebyla tak uživatelsky přátelská.
Druhou možností je zakomponovat nově vytvořený kód do Fake Game za použití grafického rozhraní již
existujícího modulu z balíčku statistic. Tento postup má ovšem také značnou nevýhodu. Ta spočívá v tom,
že metody používané k evaluaci jsou většinou velmi složité, co se týká jejich matematické stránky. Tím
pádem by bylo velice obtížné napsat odpovídající testy tak, aby pokrývaly skutečně všechny alternativy
chyb, které by mohly nastat.
Poslední varianta je převzetí evaluačního modulu z programu Weka a zakomponování ho do balíčku
statistics. Tato varianta je nejlepší, protože se při ní vyhneme problémům popsaným výše. Proto bude tato
varianta zvolena.
Propojení Weka a Fake Game
Diskuse
Důležitou otázkou je, jakým způsobem bude provedeno napojení evaluačního balíčku nástroje Weka
na prostředí Fake Game. Samozřejmě musíme co nejvíce respektovat styl návrhu zvolený vývojáři Weky
(obrázek č. 9). Opět existuje několik variant, které bych rád diskutoval.
První varianta je, že použijeme existující třídu Evaluation, vytvoříme nového potomka GameEvaluation
a všechny její metody přepíšeme tak, že budou moci přijímat objekty z prostředí Game TreeData a Model.
V rámci každé metody bude speciální volání metody, která bude mít za úkol provedení konverze dat
z formátu Fake Game do formátu Weka. Nad těmito daty se následně provedou výpočty. Tento postup není
vhodný kvůli tomu, že převod mezi objekty používanými oběma programy není úplně triviální. Weka
používá mnohem více příznaků, na základě kterých se určuje, které evaluační metody je možno použít
na kterou část dat. To by mohlo vyústit v to, že po zavolání konkrétní metody se provede převod, zavolá
se metoda mateřské třídy, ale dojde k neprovedení výpočtu. Tím pádem by došlo k zcela zbytečnému
převodu. Zároveň by ale bylo velice obtížné stanovovat tyto příznaky apriori. Znamenalo by to ke každé
metodě dopsat kontrolní kód, nikde by navíc nebyla záruka, že výpočetní náročnost tohoto kódu nebude
srovnatelná s náročností plného převodu.
Druhou variantou je provést částečnou konverzi objektů a ty pak používat. Realizace by byla taková,
že bychom vytvořili potomky tříd Instances, Classifier a Evaluation a zablokovali část jejich funkcí, které
nezbytně nepotřebujeme. To by se provedlo přepsáním metod rodičovských tříd novými, které by pouze
vyhazovaly UnsupportedOperationException. Tak bychom získali pouze funkčnost, kterou potřebujeme
pro evaluační balíček a zbytek bychom prostě nepoužívali. Tím bychom ušetřili čas na programování oproti
variantě kompletního přepsání se stejným ziskem. Bohužel, tato idea není reálně proveditelná. Třída
Evaluation totiž používá některé funkce klasifikátorů, které na první pohled s evaluací nesouvisí. Je to
například opětovné trénování modelů v případě použití křížové validace. Z tohoto důvodu není možné určit
jasnou hranici, která by oddělovala metody, které ještě jsou využity v evaluaci a které ne. Odlaďování
takového kódu by navíc bylo velmi problematické právě z důvodu značného propojení evaluačních metod
44
s metodami klasifikátoru.
Třetí a poslední je varianta plné konverze objektů mezi oběma programy. To s sebou přináší tu výhodu, že
jednotlivé fáze konverze jsme schopni snadno odspodu (attribute → instance → instances) testovat a tím
pádem bude jednoduché snáze identifikovat chyby v implementaci. Dalším znatelným plusem je i fakt,
že díky plné konverzi budeme dále moci využívat i další balíčky programu Weka, které pracují
s klasifikátory, a jejich výstupy přenášet do prostředí Game.
Řešení
Řešením, které se v tomto případě jeví jako nejlepší, je provést konverzi ve dvou krocích. V první části se
provede transformace TreeData na Instances společně s objekty, které obě třídy používají. Tím získáme
základ, oproti kterému budeme moci ověřovat účinnost modelů a provádět evaluaci. V druhé fázi pak
vytvoříme klasifikátor prostředí Weka, který bude postaven na modelech prostředí Fake Game. Takto získané
reprezentace dat a modelů potom předložíme třídě Evaluation ke zpracování. V případě, že se ale
rozhodneme použít křížovou validaci, je nutné počítat s tím, že se musí provést také konverze zpět
z Instances na TreeData, aby bylo možné provádět správné trénování v rámci jednotlivých foldů. Protože
jsou výsledky evaluace vraceny v primitivních datových typech, případně v instancích třídy String, nebude
nutné dál tento výstup upravovat. Tento výstup se pak zobrazí v grafickém rozhraní Fake Game.
TreeData
WekaToGAMETreeDataFactory
GAMEToWekaInstancesFactory
+createTreeData(Instances)
Instances
+createWekaInstances(TreeData)
GAMEToWekaClassifier
+numberOfInputs
+modelsUsed
+models
GAMEToWekaAttributeFactory
Attribute
+buildClassifier(Instances)
+classifyInstance(Instance)
+createWekaInputAtt(TreeData)
+createWekaRegressionAtt(TreeData)
+createWekaClassAtt(TreeData)
Model
Instance
GAMEToWekaClassifierFactory
GAMEToWekaInstanceFactory
+createWekaInstance(TreeData, int, Instances)
+createGAMEToWekaClassifier(TreeData, Models, int[])
Obrázek 10: UML diagram znázorňující balíček adaptérů
Na tomto obrázku (obrázek č. 10) vidíme, jak vypadá balíček, který zajišťuje výše rozebranou konverzi.
Základem je třída GAMEToWekaClassifier, která dědí od třídy Classifier z programu Weka. Jedná se
o aplikaci návrhového vzoru Adapter. Obsahuje odkazy na všechny modely Fake Game, které byly
vytvořeny. Zde je důležité si uvědomit, že může být vytvořeno více modelů na jeden výstup, mezi kterými
má být možnost přepínání. Od toho je tady proměnná modelsUsed, kde jsou v poli uložena čísla modelů.
Pořadí v poli odpovídá pořadí výstupů. Proměnná numberOfInputs potom určuje, s kolika vstupy klasifikátor
počítá. Je zde z toho důvodu, aby bylo možné hned zjistit, pokud by se uživatel pokusil klasifikovat data,
která nejsou s klasifikátorem kompatibilní.
Hlavní metody této třídy jsou následující: classifyInstance(Instance) a buildClassifier(Instances). První
z nich provádí klasifikaci vložené instance do příslušné třídy, případně regresi. Výstupem je číslo třídy, která
byla klasifikací vybrána jako správná. Konstanta CLASS_MISSING je vrácena, pokud se klaifikátor není
schopen rozhodnout, kam danou instanci zařadit. Druhá metoda je volána kdykoli, kdy má proběhnout
trénování modelu. V rámci jejího běhu se vložený objekt Instances zkonvertuje na objekt TreeData,
přes který potom proběhne trénování nativními metodami Fake Game. Zde je nutné počítat s tím, že se musí
45
zasáhnout do instance objektu Models. Prostředí totiž neumožňuje provést přímo přetrénování vybraného
modelu. Pokud se natrénuje nový model, je automaticky zařazen na konec vektoru v Models. Běžnou
evaluaci systémem Hold-out toto nijak neovlivní, ale v případě křížové validace bychom se dostali
do problémů. Proto je nutné zajistit, aby se tyto nové modely neukládaly, ale nahrazovaly své předchůdce.
Třída GAMEToWekaClassifier je vytvářena pomocí továrny GAMEToWekaClassifierFactory. Ta byla
vytvořena kvůli potřebě oddělit metody vykonávající operace nad samotnými a metody, které zajišťují
vytváření objektu. Protože je vhodné používat ji ze statického kontextu, byla aplikována jako návrhový vzor
Singleton. Jejím vstupem jsou TreeData, Models a pole int[]. První je používán čistě pro referenci, aby bylo
jasné, nad jakými daty byly dané modely vytvořeny. Na základě tohoto vstupu se inicializuje proměnná
numberOfInputs. Models obsahuje odkaz na všechny modely, které byly v prostředí Fake Game doposud
vytvořené. Zde je důležité zajistit, aby byla metoda volána až v momentě, kdy nějaké metody existují, jinak
dojde k vyhození výjimky. Toto ale lze podchytit na vyšší úrovni, proto se tímto nezabýváme. Poslední
vstupem pole specifikující modely, které budou použity. V případě, že indexy neodpovídají žádným
modelům, je vyhozena výjimka. Stejně tak je výjimka vyhozena v případě, že modely a data si neodpovídají
ať už počtem vstupů nebo výstupů. Pokud jsou data prázdná, dojde také k vyvolání výjimky.
Před
vytvořením
samotného
klasifikátoru
se
nejdříve
zavolá
metoda
továrny
GAMEToWekaInstancesFactory, která se postará o vytvoření objektu Instances. Podobně dále deleguje
jednotlivé úkoly na odpovídající továrny pro vytváření jednotlivých instancí a atributů. Atributy mají potom
rozdílný postup vytváření v případě, že se jedná o vstupní, výstupní klasifikační nebo výstupní regresní
atributy. Je to tak z toho důvodu, že každý z těchto zmíněných atributů má v prostředí Weka jiné příznaky,
které ale nejsou ve Fake Game explicitně uvedeny, a tak musí dojít k jejich vytvoření na základě vlastností
objektu TreeData. Protože se jedná o operace, které jdou snadno zaměnit a jejich záměna by byla obtížně
odhalitelná, byla jejich tvorba oddělena do tří metod.
GAMEToWekaClassifierFactory
ClassifierCreationException
GAMEToWekaClassifier
ModelSpecificationException
IncompatibilityException
GAMEToWekaInstancesFactory
IncompleteDataException
Obrázek 11: UML diagram výjimek a jejich původců
Aby byl zjednodušen proces ladění a testování programu, byla vytvořena sada výjimek (obrázek č. 11).
Jejich jména odrážejí jejich funkci. ClassifierCreationException je vyhozena v případě, že dojde k chybě při
vytváření při vytváření klasifikátoru, která ale nesouvisí s chybami dat. ModelSpecificationException je
vyhozena v případě, že modely specifikované indexy v poli modelsUsed neodpovídají modelům v Models.
IncompatibilityException je vyhozena, pokud při tvorbě klasifikátoru nebo při pokusu o klasifikaci dat dojde
k nekompatibilitě v počtu výstupů a vybraných modelů. IncompleteDataException je pak vyhozena
v případě, že data obsažená v TreeData jsou nekompletní. Za nekompletní data jsou považována taková,
která neobsahují žádné instance či mají nulový počet vstupních nebo výstupních atributů.
46
Úprava balíčku preprocessing.statistic
Diskuse
Přestože je tento balíček navržen docela dobře, i tak má jisté neduhy. Ty byly popsány v části analytické.
Otázkou je, zda je by bylo skutečným přínosem, zkoušet je nějak odstranit, nebo zda by se jednalo jen
o zbytečný programátorský purismus. Je celkem zřejmé, že v tomto případě se úpravy vyplatí, protože
sloučení výpočtů s grafickým rozhraním není do budoucna rozhodně dobrá volba. Jedná se o velice silnou
vazbu, která by do budoucna komplikovala ladění, navíc se oddělením výrazně zvýší přehlednost.
V následujících odstavcích budu uvažovat pouze změny, které nezahrnují modul pracující kolem třídy
StatisticalBlock. To je z toho důvodu, že v době vytváření této práce nebyl ještě kompletní a případné změny
rozhraní by se snadno mohli dostat do konfliktu s jeho novějšími verzemi. Pro potřeby této práce nám
postačí, že sdílí společné grafické rozhraní. Navíc jeho návrh byl proveden kvalitně a v jeho dosavadní verzi
je dobře oddělena část prezentační a výpočetní.
První uvažovanou variantou bylo sloučení všech evaluačních výpočtů pod jedno rozhraní, přes které by se
pak všechny metody shodně ovládaly. Tento postup ale není vhodný už z důvodů povahy těchto metod.
Jejich vnitřní fungování, vstupní parametry a typy výstupů jsou natolik odlišné, že se použití rozhraní nejeví
jako vhodné. Ani velice jednoduché rozhraní, které by definovalo metodu getResults() zde nelze použít. Část
výstupů je sice snadno převeditelná do formy textu a tak by se zdánlivě nabízelo použít jako návratový typ
objekt String, ale tato strategie by záhy narazila u metod, jejichž výstup je graf. Je sice pravda, že i ten by šel
převést do číselných hodnot a následně do textu, ale takový výstup by měl pro uživatele prakticky nulovou
informační hodnotu. Momentální stav, kdy je rozhraní použito na definování funkcí GUI, je tedy dostatečný.
Druhou variantou tedy bylo použití návrhového vzoru Facade, který by sjednotil evaluační metody
do jedné třídy. To by zvýšilo přehlednost, ale zároveň by si to nevynutilo standardizaci výstupů evaluačních
funkcí. Zároveň implementace podle vzoru Singleton zajistí, že evaluační metody budou přístupné i mimo
grafické rozhraní, ve kterém jsou nyní implementovány.
Součástí této úpravy pochopitelně musí být izolování výpočtů, které jsou nyní prováděny, a jejich
přesunutí do externí třídy. Tyto třídy by měly být sjednoceny do jednoho balíčku a jejich konstruktory skryty
tak, aby k nim měl přístup pouze objekt fasády. Voláním jeho metod se pak budou tyto objekty vytvářet
a zároveň bude docházet k provádění výpočtů. Výsledky těchto výpočtů budou uloženy v těchto objektech.
Tyto metody potom budou vracet celé tyto objekty.
Řešení
Základním krokem bude vytvoření balíčku core v rámci balíčku statistics, kam se budou postupně
přemísťovat evaluační metody. Každá třída v tomto balíčku bude obsahovat metody nutné k provedení
výpočtů evaluace. Zároveň musí obsahovat proměnné, které budou obsahovat výsledky. Jak u evaluací
textových, tak u evaluací grafických, by se mělo jednat o primitivní datové typy. Evaluace, kde lze výstup
převést na text, budou pouze potomky třídy Object. Grafické evaluace, jejichž výstupem jsou křivky, které se
potom zakreslí do grafů, budou dědit od třídy XYSeries, která pochází z otevřeného balíčku org.jfree.data.xy
a která představuje právě jednu křivku v grafu. (obrázek č.12)
Fasáda sdružuje metody, které vytvářejí objekty metrik a naplňují je daty na základě vstupů. Aby se
zabránilo přímému volání konstruktorů objektů, jsou nastaveny na přístup protected. Každý z objektů byl
vytvořen na základě výpočtů, které probíhaly v rámci tříd, které jsou reprezentací GUI. Původně pevně
integrovaný kód byl přesunut. Nyní objekty GUI volají metody fasády, na základě těchto žádostí se vrací
odpovídající objekt. V případě ConfusionMatrix, ConfusionMetrics a WekaEvaluationAdapter je výstup
vracen v textové či číselné formě, kterou lze přímo vypisovat. Třídy MetricsGraphData a ROCGraphData
obsahují pouze množinu kartézských souřadnic. Tyto třídy se vkládají do XYSeriesCollection. Jeden tento
objekt umí udržet neomezené množství tříd. On sám je pak vložen do objektu JFreeChart, který již tvoří
přímo graf, kde se každý objekt XYSeries zobrazí jako samostatný průběh funkce. Které třídy pracují
s jakými objekty je vidět na obrázku. (obrázek č.13)
47
ConfusionMatrix
WekaEvaluationAdapter
ConfusionMetrics
MetricsGraphData
ROCGraphData
XYSeries
EvaluationFacade
+confusionMatrix(TreeData)
+confusionMetricSingleModel(TreeData, int)
+confusionMetricSingleModel(TreeData, int, double)
+confusionMetricsMultiModel(TreeData, int)
+confusionMetricsMultiModel(TreeData, int, double)
+falseNegativeGraphData(TreeData, int, String)
+falsePositiveGraphData(TreeData, int, String)
+ROCGraphData(TreeData, int, String)
+wekaEvaluation(TreeData, Models, int[])
Obrázek 12: UML diagram statistic.core
WekaEvaluation
WekaEvaluationAdapter
ConfusionMatrix
FalsePositiveNegative
ConfusionMetrics
FalsePositiveNegativeDistribution
MetricsGraphData
ReceiverOperatorCharacteristics
ROCGraphData
Obrázek 13: UML diagram vztahů GUI a datových tříd balíčku statistic
Objekt WekaEvalutionAdapter má funkci odlišnou od ostatních částí balíčku core. Zatímco v ostatních
objektech přímo dochází k výpočtu, tento je aplikací návrhového vzoru Adapter a všechny volání
přesměrovává dál na třídu Evaluation, která je součástí kódu programu Weka. Před voláním samotných
metod v něm dochází k transformaci veškerých informací a objektů nutných k výpočtu do jejich ekvivalentů
z Weka. K tomu jsou používány dříve zmíněné továrny a adaptéry.
48
Grafické rozhraní používající evaluaci z Weka
Diskuse
Grafické rozhraní by mělo umožňovat využití všech funkcí, které má třída Evaluation se zachováním co
možná největší jednoduchosti. Protože většina procesů je již plně automatizována v rámci adaptérů, bude
potřeba implementovat jen relativně omezené množství funkcí. Bude nutné, aby bylo možné zvolit ty
modely, které mají být hodnoceny. Zároveň nesmí dojít k tomu, že by uživatel zvolil dva modely pro stejný
výstup. Dále musí být umožněno přepínání mezi systémem hold-out, leave-one-out a křížovou validací.
U té je navíc nutné, aby si uživatel mohl zvolit počet foldů, které budou použity. Zde musí proběhnout
kontrola, aby bylo číslo větší než pět a zároveň menší nebo rovno třetině počtu instancí. To vychází
z předpokladu, že vyšší číslo by byla spíše chyba na vstupu , protože pokud mu jde o větší přesnost, použil
by systém leave-one-out. Systém bootstrap se v tomto případě vůbec neuvažuje, protože se hodí k hodnocení
modelů, které jsou ze své podstaty nepřesné, takže evaluace by nebyla v přesnějších metrikách směrodatná.
Řešení
Obrázek 14: grafické rozhraní modulu Weka Evaluation
Takto vypadá grafické rozhraní modulu Weka Evaluation. (obrázek č. 14) Zobrazení výstupních atributů a
49
jejich modelů je provedeno pomocí třídy JTree, jako výstupní oblast slouží JTextArea, k vybírání
jednotlivých systémů JRadioButton, v případě křížové validace se počet foldů určuje pomocí
JFormattedTextField.
Pokaždé, když je ze stromu zvolen model, nahradí svého předchůdce od odpovídajícího atributu. Pak se
provede evaluace. Stejně tak se evaluace provede, když dojde ke změně systému nebo počtu foldů v případě
křížové validace. V případě, že je počet foldů změněn na pět a méně, je nastaven na 6 a křížová validace se
provede s tímto počtem. Stejně tak pokud je nastavena na více jak třetinu počtu instancí, je snížena na toto
číslo a provedena evaluace. Z tohoto důvodu je křížová validace zakázána pro množiny dat s počtem instancí
menším než 20.
50
Kapitola 5
Testování
Testování tohoto programu se dá rozdělit celkem do tří celků. První je manuální testování, které probíhalo
zejména v průběhu vývoje a bylo doplňkem ladění. Zaměřovalo se zejména na testování GUI. Další dvě
testování probíhaly pod frameworkem JUnit. První bylo testování adaptérů, kdy se pracovalo se speciálně
vytvořenými datovými soubory, ale krom toho byly používány běžné objekty. Cílem bylo podchytit možné
chyby v kódu, který konvertoval data z Fake Game do Weka. Druhé z nich bylo opět se speciálně
vytvořenými soubory, ale byly použity mock objekty.
Předmětem testování nebylo pouze ověření, že správné vstupy budou zpracovány dobře. Část testů se
zaměřila na to, zda jsou výjimky vyhazovány, kdy chceme, a zda program zahazuje špatné vstupy
od uživatele.
Manuální testování
První fáze se zaměřovala na odlaďování kódu v tom smyslu, že se ještě před napsáním odpovídajícího
unit testu otestovala základní funkčnost pomocí triviálních vstupů. Pokud tato prošla, pak následovalo psaní
unit testů. Toto jsem používal zejména z toho důvodu, že po odhalená chyba někdy vyžadovala větší zásah
do kódu a proto by bylo nutné přepisovat i větší část testovacích metod.
Testování GUI probíhalo velice jednoduše a omezovalo se na to, zda vyvolávané akce správně plní svoji
funkci. Snahou bylo vytvářet co nejnestandardnější vstupy, aby byla ověřena stabilita systému.
Unit testy s běžnými objekty
Testování probíhalo pomocí frameworku JUnit, konkrétně jeho verze 4.6. Pro potřeby této práce byla
Obrázek 15: vzorek kódu testů
51
předpokládána správná funkčnost těch částí programu, které nebyly přímo modifikovány a specifické testy
pro ně nebyly psány. Ostatní testy na nich samozřejmě závisely, takže případná chyba uvnitř Fake Game by
se projevila tím, že většina, ne-li všechny z nich, by neprošly. Ovšem vzhledem k tomu, že testy byly psány
tak, aby odhalily i chyby, které by při správné funkci jádra nemohly nastat, bylo by celkem snadné vytipovat.
Tyto testy se omezovaly na testování správného převodu dat z Fake Game do Weka a zpět. (obrázek č. 15)
K testování je použit zvlášť vytvořený soubor, který obsahuje předem známá data, oproti kterým je pak
testována správná funkce.
Unit testy s mock objektem
Poslední část testů, stejně jako předchozí, proběhla za pomoci frameworku JUnit. Aby bylo možno přesně
otestovat správnou funkci evaluačního balíčku, vytvořil se mock objekt DummyModel, který jednoduše
simuluje chování běžného modelu. V proměnné drží, na jaký vstup je přiřazen, a podle toho vrací výstup
na předložené vstupní atributy. Zde byl nastaven tak, že reagoval pouze na vstupy se shodnými atributy.
Konkrétně pole s hodnotami 0.1 zařadí do první třídy, hodnoty 0.2 do druhé třídy atd. Všechny ostatní vstupy
označí jako nepříslušící nikam. Zároveň byl vytvořen soubor, u kterého je předem znám počet správně
a špatně klasifikovaných. Testy se pak prováděly tak, že hodnota dané metriky byla vypočítána stranou a pak
v testu porovnána s výsledkem vráceným třídou Evaluation.
52
Kapitola 6
Závěr
Cílem této práce bylo blíže se seznámit s návrhovými vzory a evaluačními metodami a tyto
znalosti potom aplikovat v softwaru Fake Game implementací nových funkcí a upravením již
existujících tak, aby umožňovali snažší rozšiřitelnost a byly přehledné.
Prvním krokem bylo seznámení se s problematikou návrhových vzorů GoF a GRASP a popis
jejich uplatnění společně s jejich hlavními výhodami a případně nevýhodami. Dále pak proběhlo
prozkoumání nejpoužívanějších evaluačních metod data miningu. Tyto znalosti mi následně
umožnili lépe posoudit, které metriky a metody bude nutné bezpodmínečně zakomponovat do Fake
Game a které jsou spíše doplňkového charakteru.
Následovala základní analýza funkce programů Fake Game a Weka a jejich popis. Hlubší rozbor
pak byl proveden u všech částí, které se zabývají evaluací. Zde jsem krom popisu uvedl základní
nedostatky z pohledu objektově orientovaného programování. Zároveň jsem diskutoval možné
úpravy, které by vedly k lepší přehlednosti a rozšiřitelnosti. Toto jsem provedl jak u programu Fake
Game, tak u programu Weka.
Z analýzy vyplynulo, že nejlepším krokem bude použití evaluačního modulu z programu Weka.
Navrhl jsem rozhraní, které umožňuje plnou konverzi datasetu a modelů z Weka do Fake Game
a zpět. Zároveň jsem provedl takové úpravy, které umožňují práci s více modely najednou a jejich
rychlé zaměňování, které doposud program Weka neumožňoval.
Upravený modul jsem se rozhodl přidat do statistického balíčku Fake Game, kde jsem zároveň
provedl úpravu ostatních evaluačních tříd a sjednotil jejich funkce pod jednu fasádu. Nakonec jsem
vytvořil jednoduché grafické rozhraní, které umožňuje plně využít možnosti všech původních
evaluačních funkcí a mnou doplněné vlastnosti.
Finální částí bylo provedení testů funkčnosti jak manuálně, tak skrze framework JUnit verze 4.6.
Tyto testy probíhaly jak za použití reálných objektů aplikace, tak s pomoc mock objektů, jejichž
použití umožňovalo ověření funkcionality metod, kde by v reálné aplikaci figuroval příliš velký
podíl náhody.
Tato práce je přínosem pro projekt Fake Game, který doposud postrádal širší spektrum
evaluačních metrik. Tento nový modul navíc dává možnost snadného srovnání různých kombinací
modelů. Návrh byl směřován tak, aby poskytoval prostor pro případné rozšíření, eventuálně použití
v jiné části programu. Důležité je i to, že adaptéry pro konverzi mezi Fake Game a Weka jsou
použitelné univerzálně, takže se v budoucnu mohou použít i v jiných částech software.
53
54
Literatura
[1] C. Larman. Applying UML and Patterns - An Introduction to Object-Oriented Analysis and
Design and Iterative Development. 2005
[2] E.Gamma, R. Helm, R. Johnson, J. Vlissides. Design Patterns: Elements of Reusable
Object-Oriented Software. 1995
[3] O programu Weka
http://www.cs.waikato.ac.nz/~ml/index.html , stav z 23.5.2009
[4] Úvod do API programu Weka.
http://weka.wiki.sourceforge.net/Primer , stav z 23.5.2009
[5] Úvod do programu FAKE GAME
http://neuron.felk.cvut.cz/game/project.html
[6] T. Bruckhaus. Prediction and Recall Calculation
http://www.kdnuggets.com/faq/precision-recall.html , stav z 21.5.2009
[7] R. Kahavi. A Study of Cross-Validation and Bootstrap for Accuracy Estimation and Model
Selection. 1995
http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=46FDB9640A8834EABECD5235
8244A180?doi=10.1.1.48.529&rep=rep1&type=pdf , stav z 26.5.2009
[8] J. Souza, S. Marvin, N. Japkowicz. Evaluating Data Mining Models: A Pattern Language.
2002
http://hillside.net/plop/plop2002/final/PLoP2002_jtsouza0_1.pdf , stav z 24.5.2009
[9] P. Pošík. Data Mining, část I. Co to je data mining
http://cyber.felk.cvut.cz/gerstner/teaching/zbd/DataMining1-hout.pdf , stav z 23.5.2009
[10] ROC Curve Analysis, Introduction
http://www.medcalc.be/manual/roc.php , stav z 25.5.2009
[11] The Area Under the ROC Curve
http://gim.unmc.edu/dxtests/roc3.htm , stav z 28.5.2009
[12] A. Berson, S. Smith, K. Thearling. An Overview of Data Mining Techniques
http://www.thearling.com/text/dmtechniques/dmtechniques.htm , stav z 19.5.2009
[13] B. Paye. The Resurgence of Data Mining
http://www.secondmoment.org/articles/re-datamining.php , stav z 23.5.2009
[14] A Brief History of Data Mining
http://www.data-mining-software.com/data_mining_history.htm , stav z 1.6.2009
[15] R.Guiterrez. Validation
http://research.cs.tamu.edu/prism/lectures/iss/iss_l13.pdf , stav z 2.6.2009
55
56
Příloha A
Seznam použitých zkratek
FAKE GAME
Fully Automated Knowledge Extraction Group of Adaptive Models Evolution
GRASP
General Responsibility Assignment Software Patterns
GoF
Gang of Four
GUI
Graphical User Interface
CLI
Command-line Interface
Weka
Waikato Environment for Knowledge Analysis
TPr
True Positive Rate
TNr
True Negative Rate
FPr
False Positive Rate
FNr
False Negative Rate
Pre
Precision
ROC
Receiver Operating Characteristic / Relative Operating Characteristic
AUC
Area Under Curve
API
Application Programming Interface
PMML
Predictive Model Markup Language
UML
Unified Modeling Language
PDF
Portable Document Format
57
58
Příloha B
Uživatelská příručka
1. Pro spuštění použijte zdrojové kódy ve formě projektu prostředí IntelliJ Idea, main metoda se
nachází v třídě game.gui.GMHDtree
2. Nahrajte soubor iris.txt, který je součástí složky \data pomocí: File → Load
3. Vytvořte modely pomocí: Model → Create single model
4. Spusťte statistický modul: Model → Statistical evaluation of models
5. V horním roletovém menu zvolte: Weka Evaluation
6. Proběhne první evaluace modelu, automaticky jsou zvoleny první modely od každého atributu
7. Pro změnu modelů použijte strom vlevo; rozklikněte uzel atributu, jehož model chcete změnit, objeví
se nabídka modelů, kliknutí provede náhradu modelu u daného atributu a provede se evaluace tohoto
modelu v kombinaci se zbylými dvěma
8. Pro změnu systému evaluace klikněte na některé z radiových tlačítek v dolní části, zde můžete měnit
i počet foldů v případě křížové validace
59
60
Příloha C
Obsah CD
61

Podobné dokumenty

Singularita

Singularita Poznamenávám, že nenavrhuji, abychom ignorovali výzkum AI nebo na něj věnovali méně prostředků. To, co se povede v AI bude asi použitelné i v IA a naopak. Navrhuji pouze uvědomit si, že ve výzkumu ...

Více

DATA MINING - MOŽNOSTI A ZPŮSOBY JEHO VYUŽITÍ

DATA MINING - MOŽNOSTI A ZPŮSOBY JEHO VYUŽITÍ  Odhalení závislostí a rozdílů Data mining nenahrazuje, ale doplňuje dosud užívané postupy vyhodnocování hromadných dat. Dolování dat je mnohem komplexnější proces, než "prosté" výše uvedené metod...

Více