Newer
Older
% arara: pdflatex
% arara: pdflatex
% arara: pdflatex
% options:
% thesis=B bachelor's thesis
% thesis=M master's thesis
% czech thesis in Czech language
% slovak thesis in Slovak language
% english thesis in English language
% hidelinks remove colour boxes around hyperlinks
\documentclass[thesis=B,czech]{FITthesis}[2019/03/06]
\usepackage[utf8]{inputenc} % LaTeX source encoded as UTF-8
\usepackage{enumerate}
\usepackage{float}
\usepackage{amsmath}
\usepackage{hyperref}
% \usepackage{amssymb} %additional math symbols
\usepackage{dirtree} %directory tree visualisation
% % list of acronyms
% \usepackage[acronym,nonumberlist,toc,numberedsection=autolabel]{glossaries}
% \iflanguage{czech}{\renewcommand*{\acronymname}{Seznam pou{\v z}it{\' y}ch zkratek}}{}
% \makeglossaries
\newcommand{\tg}{\mathop{\mathrm{tg}}} %cesky tangens
\newcommand{\cotg}{\mathop{\mathrm{cotg}}} %cesky cotangens
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
% ODTUD DAL VSE ZMENTE++
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
\department{Katedra softwarového inženýrství}
\title{Aplikace pro předpovídání transakcí na základě finančních akcí}
\authorGN{Radek} %(křestní) jméno (jména) autora
\authorFN{Puš} %příjmení autora
\authorWithDegrees{Radek Puš} %jméno autora včetně současných akademických titulů
\author{Radek Puš} %jméno autora bez akademických titulů
\acknowledgements{Děkuji společnosti Trask Solutions a.s., zejména pak Ing. Petru Hnízdilovi a Ing. Pavlu Svobodovi, za veškeré konzultace a datové podklady k práci. Dále děkuji své přítelkyni Mariyi Tsanko, za dodání doplňujících dat ze svých bankovních účtů. Také děkuji svým rodičům, za veškerou podporu při psaní práce}
{V Bakalářské práci byl řešen problém předpovídání budoucích transakcí klientovi, na základě jeho uplynulé finanční historie. Cílem práce je pokusit se implementovat toto předvídání pomocí umělé inteligence spolu s vytvořením webového rozhraní. Toho bylo dosaženo pomocí Angularu JS, tvořící klienskou aplikaci, frameworkem .NET Core, který tuto aplikaci obsluhuje ve spojení s databází Microsoft SQL. Zabezpečení využívá JWT tokenu a o šifrování uživatelských hesel se stará RFC~2898/SHA512. Umělá inteligence byla řešena jako lineární regrese.
%=============
% <= mělo by obsahovat mojí vlastní implementaci problému
Umělá inteligence je implementována jako několik po sobě jdoucích vrstev, jejichž počet neuronů se postupně snižuje na jeden jediný, který dává informaci, zda se bude transakce opakovat, či nikoli. Aby se posléze dalo vyhodnotit, zda se transakce opravdu opakovala, byly porovnávány velikosti transakcí po jednotlivých týdnech a ty částkou si nejvíce podobné byly označeny za opakující se.
%
%Tento způsob předvídání je dále doplněn o odfiltrování trvalých transakcí, jež se už ze své podstaty vždy opakují.
In the Bachelor thesis was solved the problem of forecasting future transactions to the client, based on his past financial history. The aim of this work is to try to implement this prediction by using artificial intelligence together with creating a web interface. This was achieved by using Angular JS, a client application, with the .NET Core framework, which runs the application in conjunction with the Microsoft SQL database. Security uses the JWT token and RFC~2898/SHA512 takes care of user password encryption. Artificial intelligence was solved as linear regression.
I have implemented artificial intelligence as several consecutive layers, the number of neurons gradually decreasing to one, which gives me information whether the transaction will repeat or not. In order to assess whether the transaction was actually recurring, I compared the size of the transactions on a week-by-week basis and described the amount most similar as recurring.
%
%I have further supplemented this way of anticipation by filtering out permanent transactions, which by their very nature always repeat themselves.
\placeForDeclarationOfAuthenticity{V~Praze}
\declarationOfAuthenticityOption{4} %volba Prohlášení (číslo 1-6)
\keywordsCS{webový portál, předvídání finančních transakcí, analýza finančních transakcí, umělá inteligence, .NET Core, Entity Framework, Angular JS}
\keywordsEN{web portal, anticipating financial transactions, financial transaction analysis, artificial intelligence, .NET Core, Entity Framework, Angular JS}
\website{https://gitlab.fit.cvut.cz/pusradek/bakalarka} %volitelná URL práce, objeví se v tiráži - úplně odstraňte, nemáte-li URL práce
\begin{document}
% \newacronym{CVUT}{{\v C}VUT}{{\v C}esk{\' e} vysok{\' e} u{\v c}en{\' i} technick{\' e} v Praze}
% \newacronym{FIT}{FIT}{Fakulta informa{\v c}n{\' i}ch technologi{\' i}}
\begin{introduction}
%sem napište úvod Vaší práce ( 1 - 1,5 strany)
% - možná přidat něco jako "aktuálnost tématu"
% - možná - čím se nezabývám
% - nepatří se podnadpisy!
Ve své práci řeším problém zpracování finančních transakcí. Při výběru jsem využil možného zájmu bankovní instituce o odkoupení výsledného produktu. Ta by mohla využít mou práci k zobrazování pravděpodobných transakcí vlastním uživatelům. Případně by mohla lépe porozumět chování a potřeby klientů samotných. Tím by mohla produkty lépe cílené na zakazníky. Mě osobně navíc vždy zajímal vývoj v oblasti umělé inteligence a chtěl jsem si proto své znalosti prohloubit.
Technologie, které jsem využil pro svou práci, jsem si vybral na základě svého současného zaměstnání. Skrze společnost Trask Solutions a.s. pracuji jako externista a software developer ve společnosti ČSOB Leasing. Zde pomáhám vyvíjet aplikaci právě v jazyce C\# a frameworku ASP.NET. Avšak framework jsem použil novější (.NET Core ve spojení s Entity Frameworkem). Práci bych rád využil ke zvýšení své kvalifikace v oboru. Pro Frontend jsem zvolil Angular JS, protože jsem se chtěl také naučit něco nového. Navíc spolupracuji s týmem, který v tomto frameworku vyvíjí aplikace a v případě potřeby mi mohou obratem pomoci.
%TODO Představení struktury celé práce –obsah jednotlivých kapitol
Cílem práce je vytvoření webové aplikace, která bude pro skupinu uživatelů poskytovat službu předvídání finančních transakcí na základě jimi nahraného výpisu z účtu.
Cílem teoretické části práce je nastudování Angular frameworku, Typescriptu a Entity Frameworku Core / .NET Core. Dále je třeba zjistit možnosti využití umělé inteligence, která bude muset alespoň z části předpovědět chování uživatelů. Tato umělá inteligence bude předpovídat chování uživatelů na základě předem získaných (anonymizovaných) a obohacených dat jejich finanční historie.
Cílem praktické části je implementovat tuto webovou aplikaci, včetně zabezpečení, a pokusit se implementovat a integrovat umělou inteligenci, která bude vytěžovat údaje z uživatelem nahraných dat.
%\chapter{Analýza a návrh}
\chapter{Analýza}
Projekt je webová aplikace. Musí se proto skládat ze dvou částí: Backendu a Frontendu. Frontend je webovým rozhraním a Backend zpracovává údaje uživatele a dodává webovému rozhraní data.
\section{Webové rozhraní}
Pro webové rozhraní se nabízejí dvě možná řešení. Single Page Website a Multiple Page website. Každé má své pro a proti.
\subsection{One Page website}
Jak už název napovídá, je to web, skládající se z jediné stránky. Stránka obvykle neobsahuje příliš mnoho informací a je založena zejména na dynamičnosti prvků. Velmi často jsou to doprovodné stránky nebo krátké informativní stránky, s jejichž pomocí se subjekty na webu prezentují.
\subsection{Multiple Page website}
Tyto weby, vývojově starší, obsahují zpravidla hodně informací. Obsahují nějakou formu routování - ať už složitější, dynamickou, či jednodušší, statickou. Uživateli podávají poměrně velké množství informací. Jsou to zpravidla nejrůznější blogy, e-shopy, fóra. Jejich implementace je často snazší (zejména u statických webů), jsou schopny, často přehledněji, zprostředkovat uživateli více informací a jsou (i z historických důvodů) běžnější.
V aplikaci bude nutné zabezpečit REST API. To je možné pomocí Session anebo pomocí, novějšího, JWT tokenu. Tyto dva přístupy se v zásadě liší způsobem ukládání informace o autentifikaci uživatele. Session tuto informaci ukládá do databáze, kdežto JWT tokeny jsou uloženy u uživatele.
Ukládání u uživatele má tu výhodu, že se nemusí ukládat na serveru tolik dat do mezipaměti. Ukládání na straně serveru, v případě několika uživatelů, není nijak zásadní, avšak u většího množství to přináší podstatně vyšší nároky na server.\cite{JWTvsSessionPerformance} Navíc JWT tokeny jsou imunní vůči CSRF útoku\cite{JWTvsSessionCSRF}.
Výhodou ukládání na server je zase fakt, že je mnohem snazší znevalidnit uživatelské přihlášení - stačí odebrat záznam z databáze. U JWT je nutné vyčkat na vypršení tokenu anebo vytvořit nějakou formu blacklistu (seznam neplatných tokenů).
Na českém trhu je, co se týče předpovídání transakcí, velmi pravděpodobně zatím jediné finanční bankovnictví České Spořitelny, zvané "\textit{George}." a její doplněk "\textit{Moje zdravé finance}."\cite{George} Aplikace je přístupná pouze klientům České spořitelny a zobrazuje pouze příjmy a výdaje. V části "Moje zdravé finance" lze pak vidět, jak dlouho mi vystačí současné úspory nebo například odhadnout výši mého budoucího důchodu. Je ale schopna předpovědět některé mé budoucí transakce, tedy funkci, kterou mám za úkol implementovat. Aplikace byla spuštěna v průběhu května 2018\cite{vznikGeorge_Investujeme},\cite{vznikGeorge_Mesec} (ačkoli přesné datum jsem nebyl schopen dohledat), tedy chvíli po schválení zadání mé Bakalářské práce. To tedy dokazuje, že o témá je v praxi zájem, ale bohužel také to, že v mezičase mého vypracovávání, byl problém zpracován jinde.
Na zahraničním trhu pak existují aplikace, které umožňují klientům sledovat např. jejich měsíční útratu a na základě výpočtu jim poskytnout informaci, jestli a jak moc, překročili průměrné výdaje v tom kterém měsíci.\cite{zahranicni_aplikace}. Ve využití umělé inteligence je tedy asi Česká spořitelna, resp. Erste Group.
\begin{figure}\centering
\includegraphics[width=0.75\textwidth]{img/Moje_zdrave_finance_anonymized.png}
\caption[Moje zdravé finance]{Moje zdravé finance - předpovídání transakcí České spořitelny}\label{fig:float}
\end{figure}
\subsection{Obdobné frameworky pro umělou inteligenci}
Existuje mnoho externích knihoven, které implementují neuronové sítě. Většina je však placená a nenabízí rozhraní pro C\#. Většinou se omezují pouze na Python případně C++. Příkladem může být Opennn\cite{OpenNN}, PyTorch\cite{PyTorch}, Keras\cite{Keras}, Tensorflow\cite{TensorFlow} či Machine Learning od AWS (dceřiná společnost Amazonu)\cite{AmazonML}.
Umělá inteligence určená pro C\# je vyvíjena hlavně společností Microsoft. Ta vyvinula dva frameworky CNTK a ML.NET.
CNTK je framework zaměřený na neuronové sítě\cite{CNTK}. Z počátku obsahoval jen Python API, ale později byl rozšířen i o C\# API. V současné době dochází ještě k tvorbě Java API.\cite{CNTK_API}
ML.NET je zaměřen na .NET vývojáře\cite{MLNET}. Zároveň se snaží být více multifunkční (obsahuje i algoritmy jako K-Means\cite{MLNET_Iris}). Takové umožňuje nějaké základní generování kódu, pomocí AutoML\cite{MLNET_AutoML}, pro veřejnost, která se nezabývá detailní funkčností umělé inteligence.
\section{Obohacení dat}\label{ObohaceniDat}
Pro obohacení dat by bylo možné využít teoreticky využít veřejně dostupnou databázi MFČR - ARES (Adminstrativní registr ekonomických subjektů)\cite{ARES_zip}. Bohužel data v ní nejsou ukládána jednotným způsobem. Je sice zadefinována základní struktura dokumentu\cite{ARES_struktura}, avšak data v ní nejsou nijak strukturována. Živnosti jsou zadaný naprosto nahodile a není využito žádného oficiálního klíče. Nedefinované hodnoty obsahují výrázay jako: "0", "null", "NULL", "prázdné", "nic", "není", "nedefinováno",... Jako nejlepší příklad záznamu v databázi by pak mohla dobře posloužit Komerční banka. Ta nemá dokonce definováno vůbec nic, až na popis, který obsahuje necelých 8000 znaků. Lze tedy usoudit, že využití tohoto zdroje je téměř nemožné a pro obohacení se nehodí.
Další možnost, která by se nabízela je využití bankovních symbolů. Variabilní a specifické symboly opět neobsahují žádné informace. Někdy do nich bývá zadáváno IČO, které by se dalo napojit na ARES, ale jak už je zmíněno výše, toto napojení nepřipadá v úvahu.
Zbývají tedy už jen Konstantní symboly. Ty se bohužel využívají pouze v rámci České Republiky, ale mají alespoň částečně definovanou strukturu. A ačkoli její použití již není povinné, ve výpisech z účtů, které byly pro tuto práci získány, se vyskytují hojně a mohou o transakcích něco říci.
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
\section{Transakce}
Od uživatele je vyžadován nějaký vstup. Pro ten je nutné definovat nějaké minimální informace. Protože každá banka tvoří výpisy z účtu nepatrně jinak, došlo k omezení na tyto informace:
\begin{enumerate}[1)]
\item datum
\item částka
\item konstantní symbol
\end{enumerate}
Z data transakce lze snadno zjistit, o jaký den se jednalo i jestli k transakci došlo o víkendu. Částka jednoduše označuje velikost transakce. Konstatní symbol pak pomáhá obohatit data o další vstupy, jak již bylo zmíněno v kapitole \ref{ObohaceniDat} Obohacení dat.
Transakční historie obvykle obsahuje ještě další údaje, ty však bohužel často liší banka od banky a proto je nelze použít. Příkladem zde může být Typ transakce, který je označen v každé bance jinak.
%TODO viz. příloha *.csv csas + csob + airbank
\section{Ukládání dat}
Aplikace bude muset umožňovat ukládat uživatelské účty a zároveň k nim i transakční historii od uživatelů. Je tedy vhodné vytvořit nějakou formu databáze.
\subsection{Uživatel}
Za první část databáze by se dali považovat samotní uživatelé, kteří budou do aplikace přistupovat. Je nutné si pro ně pamatovat uživatelské jméno a heslo. Heslo samozřejmě musí být uloženo v šifrované podobě.
\subsection{Uživatelská data}
Druhá část, ukládání uživatelských dat, je náročnější. Je potřeba zvážit, jak je ukládat. Veškerá data totiž budou přístupná z csv souborů ("\textit{Comma-Separated Values}" - čárkou oddělené hodnoty)\cite{csv_name}. Z toho důvodu se nabízí dvě možnosti:
\begin{enumerate}[a)]
\item Ukládání ve formě NoSQL
\item Parsování transakcí do podoby nějakého relačního modelu a uložení v něm.
\end{enumerate}
Ukládáním, ve formě NoSQL, je myšleno ukládání dat, jak přijdou od uživatele s minimálními úpravami (as-is). Pro veškeré operace s uživatelskými daty by se využívala jedna \mbox{"velká tabulka"/super-entita.} Z transakcí samotných lze vyvodit nějakou jistou strukturu a v tom případě bude docházet k zbytečně velké redundanci dat.
Druhou možností je transakci rozdělit na několik částí / tabulek. A s těmi následně pracovat. Výhodou zde je Práce s menšími daty i menší databází.
\subsection{Neuronová síť}
Neuronová síť je tvořena pomocí vrstev, neuronů a vah vstupů. Ukládání těchto dat přímo vybízí k uložení ve strukturované databázi - konkrétně rozdělené přímo na tyto samostatné celky.
Pro webové rozhraní byla zvolena, One Page website, doplněná o stránky s registrací a přihlášením. Není potřeba uživateli předávat velké množství informací. V zásadě jen zobrazovat grafy a předpoklady. Nemusí se tedy vytvářet rozsáhlý web a jen jednoduché routování. V případě malého množství stránek se navíc snadněji pracuje s responzivitou, protože ji stačí vyladit na jednu, resp. tři stránky webu. Jakákoli práce s responzivitou pro každou další stránku pak zvětšuje prostor na chybu.
%TODO highcharts, bootstrap, angularmaterial, interceptor,
\section{Zabezpečení}
V případě zabezpečení komunikace mezi backendem a frotendem (API) bylo využito JWT tokenu. Kromě výhod, uvedených v analýze, je tento přístup k zabezpečení i novější (dle Wikipedie poprvé vydán 28.12.2010\cite{JWT_published} - v průběhu psaní práce starý necelých osm let) a umožní vyzkoušet si novou technologii.
Pro zabezpečení routování na straně Klienta bylo využito tzv. Guardů - součást zabezpečení přímo v Angular frameworku. A konečně k zabezpečení uživatelských hesel se využilo hashovacího algoritmu RFC~2898/SHA512. Zároveň se pro každé heslo generuje jiná sůl a proto by nemělo být možné v databázi najít dvě stejná hesla se stejným hashem.
Aby bylo možné činit nějaké předpovědi, je nutné od uživatele získat nějaká data. Toho bylo docíleno na základě nahrání vyexportované transakční historie z banky uživatele. Ta musí být zároveň vyexportována ve formátu CSV.
Celý import začíná na webovém rozhraní. Zde uživatel vybere soubor a stiskne tlačítko "nahrát". To způsobí zahájení celého procesu parsování dokumentu a jeho ukládání do databáze.
Interně celý proces probíhá tak, že dojde k zavolání nějaké funkce, jež převezme daný soubor a skrz API pošle na server. Při tomto požadavku se pak automaticky (jako při každém volání API) zavolá tzv. "Interceptor". Ten vloží do hlavičky volání ještě údaj o JWT tokenu, aby server mohl rozpoznat, zda-li je volání oprávněné či nikoli. JWT token navíc obsahuje údaje, které říkají, kterému uživateli tento požadavek náleží.
Po zpracování požadavku na frontendu, dojde ke zpracování požadavku na serveru. Ten ověří, zda-li je uživatel přihlášen a soubor je v pořádku a zároveň již nebyl nahrán soubor se stejným jménem pro daného uživatele. Pokud ano, pošle soubor dále ke zpracování. V opačném případě vrátí HTTP status BadRequest a dál nepokračuje.
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
Pokud došlo k úspěšnému zpracování požadavku, dojde k parsování souboru. K tomuto procesu byla využita externí knihovna s názvem CsvHelper\cite{CsvHelper}.
Tato knihovna potřebuje k úspěšnému zpracování dokumentu nadefinovanou třídu, jež obsahuje veškeré položky, které mají být v dokumentu vybrány. Přestože by pro extrakci stačilo vybrat pouze částku, datum a KS, bylo načteno podstatně více údajů pro případné rozšíření aplikace. Veškeré načítané údaje jsou proto následující:
\begin{itemize}[--]
\item typ účtu
\item číslo účtu (včetně kódu banky)
\item datum zaúčtování
\item částka
\item měna
\item zůstatek
\item číslo protiúčtu (včetně kódu banky)
\item konstantní, specifický, variabilní symbol
\item typ operace
\item ID transakce v bance
\item poznámka
\end{itemize}
K výše zmíněnému výčtu je však nutno zdůraznit, že ne všechny položky jsou povinné. V práci došlo na omezení se na pouze dvě povinné položky a totiž datum zaúčtování a částka. V případě chybějícího čísla účtu dochází k jeho nahrazení ID uživatele s kódem banky "857368". Tato hodnota je ekvivalentní textu "UID" (User ID - uživatelské ID) v ASCII tabulce (kódová tabulka pro znaky anglické abecedy).
%TODO ref csv soubory
Při realizaci bylo myšleno i na různá pojmenování napříč jednotlivými bankami a k pokusu o vytvoření maximální unioverzálnosti řešení. Proto se pro některé položky definovalo více názvů. Příkladem tak může být položka "označení operace", jak je pojmenována v ČSOB a "typ transakce", což je ekvivalent v České spořitelně.
Relativně překvapivým problémem je však parsování částky transakce. Při exportu dat totiž může být ve formátu "1 234.56" - s mezerou, oddělující řády. Také ale může obsahovat rozdílné oddělovače desetinných míst, př. "12,35". Problém mezery však lze snadno vyřešit povolením této skutečnosti při parsování pomocí metody, v .NET frameworku, System.Parse.
Problém desetinné čárky není o tolik těžší. Před parsováním stačí částku projít a nahradit znak ',' za '.'. Tím dojde k unifikaci čísla.
Po zparsování dokumentu dochází k ukládání pouze těch záznamů, které se podařilo úspěšně zpracovat. Všechny neúspěšné záznamy jsou přeskočeny. Zároveň dochází k založení záznamu o nahraném souboru. Ten obsahuje jen jméno souboru a identifikaci, uživatele, který ho nahrál. K tomu to záznamu se posléze přiřadí veškeré transakce, které byly tímto souborem nahrány. Děje se tak z důvodu, že by uživatel chtěl daný soubor smazat.
\subsection{Obohacení}\label{RealizaceObohaceni}
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
Protože data z ARES nelze smysluplně zpracovat, došlo k obohacení data na základě konstantních symbolů. Tento prvek sice nemusí být přítomen v transakci, pro operace, jež má na starosti banka (karetní operace, výběry z bankomatu,...), jsou však často přítomny.
Přidání závislostí na konstantních symbolech bylo založeno na číselníku MFČR. V práci pak bylo konkrétně využit jeho souhrn ze serveru Finance.cz\cite{ConstantSymbolList}. Číselník byl zároveň rozdělen do následujících kategorií:
\begin{enumerate}[a)]
\item Druh
\begin{itemize} [--]
\item označení druhu transakce
\item platby za zboží a služby, mzdové náklady,...
\end{itemize}
\item Dle významu poslední číslice
\begin{itemize} [--]
\item označení druhu platby
\item hotovost, dobropisy, přednostní platby,..
\end{itemize}
\item Spravované MFČR
\begin{itemize} [--]
\item popisují vztahy ke státnímu rozpočtu a rozpočtům místních samospráv
\item dotace, daně, cla, pokuty, penále,...
\end{itemize}
\item Rezervované symboly
\begin{itemize} [--]
\item symboly rezervované pro mezibankovní styk
\item platby kartou, šekem, platby na neexistující účet,...
\end{itemize}
\end{enumerate}
Dále existuje ještě i sada zahraniční konstantní symbolů. Sada shrnuje různé druhy plateb do dvaceti různých kategorií. Vzhledem k faktu, že se pro práci nepodařilo zajistit žádné výpisy z účtu, jež by obsahovaly zahraniční platby, tato sada nebyla využita. Byla však definována pro případné pozdější rozšíření dat.
%TODO opravdu?
%\section{Triviální repetitivnost}
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
\section{Umělá inteligence}
Pro předpovídání budoucích transakcí je využita neuronová síť. Tedy síť, na způsob lidského mozku, která obsahuje množství neuronů. Celá tato síť pak funguje tak, že pokud dojde k aktivaci nějakého neuronu, tak ten postupně ovlivní jeden, či více dalších neuronů a ty zase další. Míru aktivace pak ovlivňují tzv. váhy pro každý z předchozích neuronů (vstupů). Způsob jejího fungování velmi názorně ukazuje např. Grant Sanderson ve svém videu "But what is a Neural Network?"\cite{ANN_Understanding}
Aby tedy neuronová síť mohla fungovat, potřebuje nějaká data, která by aktivovala vstupní neurony. Tato data musí být přizpůsobená tak, aby se tvářil, že byla výstupem jiných neuronů - musí být "normalizovaná".
Dále potřebuje nějaká data za pomoci kterých, by si mohla nadefinovat, na kolik budou jednotlivé neurony ovlivňovat ty ostaní. Jinýmy slovy data, podle kterých se bude síť učit předvídat. To jsou v této aplikaci veškeré transakce, jež se opakují.
Lze tedy pozorovat, že implementace předpovídání transakcí je poměrně rozsáhlá. Proto byla rozdělena do několika konzolových aplikací. Každou z těchto částí je tak možné nezávisle implementovat i testovat. V případě potřeby je možné takto i jeden modul reimplementovat a nedojde k ovlivnění dalších. Ve výsledku byla proto umělá inteligence rozdělena následovně:
\begin{enumerate}
\item Datafeeder
\begin{enumerate}[--]
\item část aplikace, která slouží k postupnému čtení dat z databáze a k předání dalším objektům (částem aplikace)
\item tato část má na starost zároveň i normalizaci dat
\end{enumerate}
\item Komparátor
\begin{enumerate}[--]
\item udává, které transakce se opakovaly a které nikoli
\end{enumerate}
\item Neuronová síť
\begin{enumerate}[--]
\item na základě vstupních dat se pokusí předpovědět výsledek
\end{enumerate}
\end{enumerate}
\subsection{Implementace základní části neuronové sítě}
Samotná neuronová síť je stále velký celek, který bylo potřeba rozdělit na podobjekty. Bylo tak tedy učiněno dle logických celků - nejdříve se dělí na jednotlivé vrstvy. Vrstvy mohou být:
\begin{enumerate}[a)]
\item Vstupní vrstva
\begin{enumerate}[--]
\item prochází přes ni veškeré vstupy do neuronové sítě.
\item svůj výstup předává vnitřním vrstvám
\item je první a zároveň, v rámci sítě, unikátní vrstvou
\end{enumerate}
\item Vnitřní/skrytá vrstva (vstupně-výstupní)
\begin{enumerate}[--]
\item přijímá vstup z předchozí vrstvy, zpracovává jej a předává dál
\item vstup může být buď přijímán buď ze vstupní vrstvy, popř. z jiné vnitřní vrstvy.
\item výstup je předán buď opět do další, vnitřní vrstvy, anebo konečné výstupní.
\end{enumerate}
\item Výstupní
\begin{enumerate}[--]
\item stejně jako vstupní vrstva je unikátní
\item přijímá vstupy z vnitřní vrstvy vyhodnocuje je
\end{enumerate}
\end{enumerate}
Každá z těchto vrstev následně obsahuje sadu neuronů a každý neuron obsahuje právě jednu sadu vah. Tato sada je složena z desetinných čísel jejichž počet je ekvivalentní množství neuronů v předchozí vrstvě. Jedinou výjimkou je vrstva vstupní. Ta má neurony nahrazeny sadou vstupů (jeden vstup je ekvivalentem jednoho neuronu).
Tímto způsobem je vytvořen tzv. úplný k-partitní graf.
\begin{figure}[h]
\includegraphics[width=0.75\textwidth]{img/artificial-neural-network.png}
\centering
\caption[Struktura neuronové sítě]{Struktura neuronové sítě\cite{ANN_structure}}
\end{figure}
Při předvídání výsledku se do počáteční (vstupní) vrstvy vloží vstupy. Tato vrstva je pošle do vrstvy vnitřní. V této vnitřní vrstvě se v každém neuronu všechny vstupy vynásobí s korespondujícími váhami a následně se sečtou. Výsledné číslo projde přes nějakou formu aktivační funkce ("squashing function"), která sníží velikost hodnoty na číslo v intervalu \textless -1;1 \textgreater .
Vzhledem k náročnosti na pochopení výroku výše, je pro lepší ilustraci, přiložen obrázek č. \ref{single-neuron}. Na obrázku jsou znázorněny jednotlivé vstupy neuronu (kompletní sada vstupů vrstvy) pomocí značek X1 - X3. W1 - W3 označuje váhy, kterými se vstupy násobí. Váhy směřují do aktivační funkce, která udržuje hodnotu výstupu v daném intervalu. Y je označuje výstupní hodnotu.
\begin{figure}[h]
\includegraphics[width=0.75\textwidth]{img/neural-network-single-neuron.png}
\centering
\caption[Průchod neuronem]{Průchod neuronem\cite{ANN_neuron}}
\end{figure}
Výstup jednotlivých neuronů vytváří sadu dalších vstupů pro další jednu vrstvu v pořadí. Tímto způsobem se postupně prochází veškeré vrstvy, až po vrstvu výstupní. Výstupní vrstva se liší od všech ostatních pouze tím, že obsahuje jeden neuron. Výstup toho neuronu lze uvažovat jako pravděpodobnost, na kolik je něco pravda či nikoli. V kontextu současné práce to znamená, jestli se daná transakce opakovala, či nikoli.
Příkladem by se dalo uvést následující: Pokud získám ze sítě hodnotu blízkou -1, transakce se pravděpodobně nebude opakovat. Analogicky pokud získám hodnotu blízkou 1, transakce by se měla opakovat. Zároveň platí, že čím více je výsledná hodnota blíže 0, tím menší je pravděpodobnost správné předpovědi.
Při bližší pohledu na fungovaní algoritmu si lze všimnout, že při násobení a sčítání vah platí následující vztah:
\begin{figure}[h]
\[ \begin{bmatrix} x_{1} \\ x_{2} \\ x_{3} \\ \vdots \\ x_{n} \end{bmatrix} \cdot
\begin{bmatrix} w_{1}, w_{2}, w_{3} \dots w_{n} \end{bmatrix} =
S
\]
\end{figure}
Kde 'x' značí vstupy a 'w' váhy. 'S' je výsledek před vstupem do aktivační funkce.
%TODO opravdu použít href???
Právě z toho to důvodu jsou v řešení uvažovány váhy i vstupy jako vektory, které se navzájem násobí. K násobení vektorů je využito externí knihovny
\href{https://numerics.mathdotnet.com/}{[Math.NET Numerics]}. Aktivační funkce je pouhá hyperbolická funkce tangens z integrované knihovny Math.Tangh()
\subsubsection{Učení}
Aby síť měla nějakou vypovídací hodnotu, musí se nejdříve naučit, co má předpovídat. Prvotní předpovědi jsou čistě náhodné. Děje se tak proto, že při inicializaci jsou váhy v jednotlivých neuronech čistě náhodné. Je tedy nutné provést korekci vah a tím síť učit. Tomuto procesu se říká zpětná propagace ("backpropagation"). Nutnou podmínkou pro takové učení je pak samozřejmě, že je známý korektní výstup pro daný vstup.
Korekce probíhá tak, že síť nejdříve vyhodnotí nějaký vstup. Poté ji je řečeno, jaký byl očekávaný výsledek. Na základě rozdílu očekávaného výsledku a skutečného výsledku se vyhodnotí chyba pro výstup. Ta se následně musí propagovat napříč celou sítí. Musí se ale také brát v úvahu, že ne každý neuron přispěl stejnou měrou k výsledné chybě. Je nutné najít přesnou chybu pro každý z neuronů.
K tomuto výpočtu se dá využít vzorec:
\begin{figure}[H]
\[ \gamma = error \cdot (1 - output^2) \]
\end{figure}
Přičemž \textit{error} je chyba neuronu, \textit{output} výstup neuronu po průchodu aktivační funkcí a \textit{\textgamma} by se dala pochopit jako chyba vstupu současného neuronu. Chybu jednotlivých vah lze najít vynásobením vstupů do neuronu (vektorem) a vypočítané, skalární, hodnoty \textgamma, díky čemuž vznikne nový vektor. Tento vektor už po té stačí jen přičíst ke korespondující váze, čímž dojde k její opravě.
Je však stále třeba zjistit chybu každého celého neuronu ve vnitřní vrstvě, aby bylo možné využít výše zmíněný vzorec. Ve výstupní vrstvě je toho dosaženo, již zmíněným odečtením referenčního výsledku od předpokládaného. Pro vnitřní vrstvy tento způsob ale použít nelze. Zde toho je dosaženo tak, že se v každé vrstvě násobí vypočtená hodnota \textgamma s korespondujícími váhami neuronu a vektorově se tyto hodnoty sečtou. Výsledný vektor se vždy předá předcházející vrstvě jako seznam chyb každého z neuronů. Celý proces předávání vektoru chyb funguje na obdobném principu, jako předchozí vyhodnocování pravděpodobnosti. V tomto případě je postup ale opačný a vyhodnocuje se postupně od výstupní vrstvy ke vstupní.
Detailní odvezení vzorce (ačkoli pro odlišnou implementaci neuronové sítě) přehledně vysvětluje uživatel, vystupující pod přezdívkou \textit{The One} na svém videu o tvorbě neuronových stí.\cite{ANN_BackPropagation}
Jedním z problémům při učení neuronové sítě mohou být také vstupy samotné. Pokud se síť bude učit po samostatných vstupech a tyto vstupy budou rozděleny na samostatné celky, může se síť naučit nejdříve jeden a později přeučit na druhý.
Pokud se naopak využijí všechny vstupy najednou, může u velkých datasetů dojít ke značným problémům s mezipamětí. To může způsobit načítání vstupních dat samotných ale mnohem pravděpodobněji alokované prostředky ve vnitřních strukturách každého neuronu. Konkrétně jde o ukládání, vypočítaných korekcí jednotlivých vah, v generické kolekci \textit{List}. Ta se při dosažení maxima svého objemu automaticky realokuje na násobek současného. Tím vzniknou několikanásobky velikosti původního setu dat. Navíc se zjistilo, že tento přístup není ani příliš efektivní z hlediska učení.\cite{minibatchVsFullBatch} Pro učení je tedy využit přístup, který rozděluje data do několika, ne nutně stejně velkých, ale relativně malých, celků ("minibatch"). Tento celek se nejdříve celý vyhodnotí a váhy jsou upraveny na základě průměru všech korekcí v něm.
Tento přístup uspoří paměť, je schopen se lépe učit a zároveň tím lze eliminovat problém, kdy chodí data jednoho druhu a po sléze jiného (nemají uniformní rozdělení). Síť by se totiž připravila jen na jeden druh dat. Což je zároveň problém, ke kterému došlo kvůli porovnávání transakcí (detailně rozebráno v sekci \ref{komparator}).
\subsection{Export, Import sítě}\label{ANNexportImport}
Aby bylo možné využít už jednou natrénovanou síť, je nutné si ji nějakým způsobem zapamatovat. Pro síť jsou důležité pouze dvě věci a totiž váhy neuronů společně s tvarem sítě. Tvarem sítě se rozumí množství vrstev a počet neuronů v nich obsažených.
Pro řešení uložení sítě si ji lze představit jako 3D objekt. Prvním rozměrem jsou vrstvy, druhým počet neuronů v každé vrstvě a třetí jsou váhy v každém neuronu. Stejným způsobem se proto ukládají resp. načítají do/z databáze.
\subsection{Testování funkčnosti neuronové sítě}
Pro zjištění funkčnosti sítě musely být vytvořeny nějaké dva primitivní problémy, na základě kterých by se dalo ověřit, že opravdu funguje. Byl tedy zvoleno předvídání sudých a lichých čísel společně s testováním operátoru XOR pro dvě čísla. Pro oba testované případy byl implementován čítač pokusů - kolik bylo správně a kolik špatně i kolikrát v testu mělo dojít k předpovědi o správném či špatném výsledku. Tento čítač zároveň ověřuje, jestli síť nepředpovídá jen jedno číslo případně generátor, který testy provádí funguje správně.
Dále bylo třeba zjistit, zda při exportu sítě a následném importu nedojde k porušení struktury sítě a bude fungovat i nadále.
\subsubsection{Sudá a lichá čísla}
Prvním bylo rozhodování se, jestli je číslo mezi nulou a sedmi sudé nebo liché. Čísla 0-7 byla zvolena protože je lze zapsat pomocí tří cifer v binární soustavě. Jediný rozdíl byl, že se číslo 0 zapisovalo jako -1. To je z důvodu že 0 není neutrální číslo pro násobení a tím pádem by nedocházelo ke správnému vyhodnocování vah. Využití čísel -1 a 1 bylo doporučeno i na konferenci Microsoftu \textit{Build 2013 - Developing Neural Networks using Visual Studio}\cite{MicrosoftBuild2013}. Při testování se podařilo síti předpovědět, zda-li je číslo sudé či liché na 100\% (viz. obr. č. \ref{OddEvenTest}). Síť byla ve formě 3 - 3 - 3 - 1 s 1000 vstupy a minibatchem o velikosti 100. Vzhledem k jednoduchosti testu (výsledek závisí jen a pouze na jednom vstupu - ostatní jsou nepodstatné), změny na tvaru sítě neměly žádný větší vliv.
\begin{figure}[h]
\includegraphics[width=0.75\textwidth]{img/Odd_Even_Test_Evaluation.png}
\centering
\caption[Test sudých a lichých čísel]{Test sudých a lichých čísel}
\label{OddEvenTest}
\end{figure}
Druhým problémem byl operátor XOR. Tento operátor označuje množinovou operaci která je pravdou pouze pokud jedno z čísel má nulovou, resp. zápornou (-1), hodnotu a druhé kladnou (1). Jak už bylo naznačeno test pro test byla nulová hodnota nahrazena zápornou ze stejných důvodů, jako v předchozím testu.
První test probíhal na síti ve tvaru 2 - 3 - 3 - 1 s 1000 vstupy a minibatchem o velikosti 100. Kde první číslo (2) značí vstupy a poslední (1) značí výstupy. Výsledek testování dosáhl úspěšnosti 67.1\% (viz. obr. č. \ref{XORTest}).
\begin{figure}[h]
\includegraphics[width=0.7\textwidth]{img/XOR_Test_Evaluation.png}
\centering
\caption[Test XOR operátoru s málo neurony]{Test XOR operátoru s málo neurony}
Bylo by možné tedy uvažovat, že téměř 3/4 vstupu byly odhadnuty správně, výsledek je proto lepší než čistý odhad a lze jej považovat za dostatečný. Problém ale je, že síti byly poskytnuty veškeré možné vstupy a tudíž musí předpovědět 100\%.\cite{XORProblem} Řešením tedy je třeba přidat větší množství neuronů a dat pro učení. Bylo proto zvoleno tvaru 2-3-4-2-1 s 10 000 vstupy a minibatchem opět velikosti 100. Tenkrát bylo dosaženo lepšího výsledku (obr. č. \ref{XORTestSuccess}).
\begin{figure}[h]
\includegraphics[width=0.75\textwidth]{img/XOR_Test_EvaluationSuccess.png}
\centering
\caption[Test XOR operátoru s doplněnými neurony]{Test XOR operátoru s doplněnými neurony}
\label{XORTestSuccess}
\end{figure}
Zároveň na zmíněném testu lze i vidět, že tvar a velikost sítě mají vliv na její výstup.
\subsubsection{Export, Import}
Export a import sítě lze ověřit snad jen jediným způsobem. A totiž exportováním již natrénované sítě a jejím následným naimportováním zpět. Pokud došlo ke korektnímu importu, síť bude nadále správně předvídat testovaná data.
Bylo tedy implementováno simulované exportování a importování sítě a ověřeno, zda-li se předpovědi nezměnili. Výsledek opět dosáhl 100\%, proto lze předpokládat, že funkčnost je bezchybná (viz obr. č. \ref{ImportExportTest}).
\begin{figure}[h]
\includegraphics[width=0.75\textwidth]{img/test_export_import.png}
\centering
\caption[Test exportu a importu sítě]{Test exportu a importu sítě}
\label{ImportExportTest}
\end{figure}
\subsection{Komparátor} \label{komparator}
Proto, aby mohlo neuronová síť vyhodnocovat, jestli se daná transakce opakuje, je nutné z dat nejdříve určit, které transakce se konkrétně opakovali. Tento úkol bohužel není jednoznačný.
První myšlenka, která mnoho lidí napadne, je porovnávání výše transakce. Pokud jsou dvě transakce stejně velké, automaticky se opakují. To bohužel není pravda. Lze ilustrovat na jednoduchém příkladu: Řekněme, že nějaký člověk, říkejme mu třeba Karel, si chodí ráno před prací kupovat snídani. Pokaždé si v obchodě koupí čerstvou bagetu. Problém ale nastává, pokud se bageta zlevní či zdraží, což je situace, která nastává relativně často. Bageta může být také někdy vyprodaná. Karel si stejně tak může každé ráno kupovat třeba pomeranče. To je položka, která nemá nikdy stejnou hodnotu a případné změny v ceně ještě zvyšují amplitudu. Navíc pomeranče mohou být ve špatném stavu, což ho bude nutit měnit potravinu, kterou kupuje. Tudíž není možné se rozhodovat podle identické ceny.
Druhá, související myšlenka, pak bývá: Pokud se nelze orientovat podle ceny, tak je možné se orientovat dle místa, potažmo čísla účtu. Tento případ opět není možný. Budeme-li dále používat Karla jako příklad, řekněme, že si kupuje ráno kávu. Pokud je venku pěkně, jde si ji koupit do stánku kde se prodává levná a dobrá. Musí se ale posadit na lavičku v parku. Pokud ale hezky není jde si ji koupit do kavárny, tedy úplně jiného podniku s úplně jiným číslem účtu. Stejně tak mohl zaspat a kávu si koupí až dotovanou v práci, třebaže mu příliš nechutná. V tom případě si koupil kávu za úplně jinou cenu a ještě na úplně jiném místě s úplně jiným číslem účtu. Všechno to však lze považovat za opakující se transakci.
Jako možné řešení, které bylo implementováno, tedy je srovnávat transakce ze dvou různých časových úseků. V práci bylo přikloněno k rozsahu jednoho týdne.
Jeden den je příliš malý rozsah, kdy se může stát, že dokonce nedošlo k žádné transakci. Pokud by se porovnával měsíc, transakcí je poměrně mnoho. Běžný člověk má navíc obvykle při opakující se činnosti zažité určité rituály. Nejrozšířenější opakující se činnost bývá chození do práce či školy přes týden. Opakující se rituál potom může být pití kávy po příchodu do práce. Takové činnosti se opakují právě v rámci týdnů a porovnávání by tedy mělo být také v rámci násobků týdnů.
V praxi se rozlišují i aktivity na sudé a liché týdny (cvičení ve škole, pravidelné schůzky v práci, jež se konají ob jeden týden). Ideální by tedy bylo porovnávání transakcí po dvou týdnech. Z nedostatku rozsahu obdržený dat došlo ale k přiklonění se pouze k týdnu jednomu.
Pokud tedy budou uvažovány transakce ze dvou různých týdnů, měla by se opakující se transakce vyskytovat v každém týdnu právě jednou. V jednom z týdnů ale bývá z pravidla transakcí více. Proto by se dalo optimistickým přístupem (člověk po většinu času opakuje činnost) říci, že opakujících se transakcí je právě minimum z počtu transakcí v těchto dvou týdnech. Zároveň jsou v relaci 1:1 - každá opakující se transakce v prvním týdnu má pravě jednu opakující se transakci v týdnu druhém. Zbylé transakce se neopakují.
Pro přiřazování do párů se procházejí v cyklu transakce a ke každé transakci se vybere nějaká, která je ji hodnotou nejblíže. V každém průchodu cyklu se pro každou transakci z menší množiny hledá transakce z množiny větší taková, že rozdíl v jejich částce je nejmenší (tzv. vzdálenost musí být nejkratší). Při hledání těchto dvojic může dojít k duplicitnímu propojení (dvě a více transakcí z jedné množiny, považují jednu transakci z druhé množiny za nejbližší). V tom případě se vezme dvě nejkratší vzdálenosti z tohoto vztahu. Celý cyklus se opakuje, dokud nejsou přiřazeny všechny transakce z menší množiny k množině větší.
\subsubsection{Porovnávání vzdálenosti}
S touto implementací však vyvstává jeden problém. Toto "optimistické" přiřazování transakcí ve skutečnosti říká, že týden s menší aktivitou je podmnožinou týdne s aktivitou větší. Jinými slovy - všechny platby jednoho z týdnů jsou bezezbytku obsaženy v druhém. To zcela jistě není správně. Opakující se transakce jsou spíše průnikem těchto dvou týdnů (ne všechny se opakují). Je tedy opět třeba se zamyslet, jakým způsobem toto vyřešit.
První možností by bylo omezit počet opakování v cyklu, kdy se párují transakce. Ať už říci, že se cyklus nesmí procházet např. více než třikrát anebo musí zůstat alespoň 5 nerozhodnutých transakcí. Při využití těchto přístupů ale nemám žádnou kontrolu nad samotnými transakcemi. Mohou mi zbýt transakce, které si jsou částkou blízké - to nastává třeba v případě, že dotyčný člověk jednoduše nenakupoval nic navíc a částky jsou si opravdu podmnožinou. Tak je možné, že mezi jednotlivými týdny nebyl finančně příliš aktivní a částek je jen málo - všechny by se mohly vyfiltrovat jako neopakující se. To tedy nepoukazuje na dobré řešení.
Za mnohem korektnější přístup, by se dalo považovat porovnávání ještě podle relativní vzdálenosti jednotlivých částek. Tím je míněno, že hodnoty 10~Kč a 110~Kč se od sebe liší více, než například 5~000~Kč a 5~100~Kč. Obě hodnoty se v absolutním měřítku sice liší jen o sto korun ale částky samotné se pohybují ve zcela jiných řádech. Avšak porovnávání řádů s hodnotou je poměrně abstraktní a jednoduché porovnání řádů s rozdílem částek nejde příliš jednoduše implementovat.
Za řešení lze považovat pohled z hlediska poměrů. Pokud se zůstane u předchozích částek daly by se uvést do poměrů 110~:~10 a 5~100~:~5~000. Poměr pro první zmíněnou částku je roven 11, kdežto pro druhou 1.02. Zde už lze zřetelně vidět, jak moc se od sebe částky relativně liší.
Za povšimnutí však ještě stojí, že je třeba poměřovat vždy částku větší vůči menší, případně naopak. Je však nutné dodržovat pořadí velikostí. Po samotném přiřazení párů navíc není garantováno, která z částek je větší. Mohlo by tedy dojít k tomu, že by se porovnávala čísla normalizovaná do velikosti menší než jedna, s čísly většími než jedna. Takové porovnávání by dávalo zcela nesmyslné výsledky.
%TODO možná noise
Ačkoli komparátor, jako takový, je poměrně složitý, jeho výstup už tak složitý není. Vše lze porovnat pouhým okem z výpisu. Příklad vygenerovaného výpisu, s daty z poskytnuté transakční historie, je na obr. č. \ref{ComparatorTest}.
\begin{figure}[h]
\includegraphics[width=0.75\textwidth]{img/ComparatorTest.png}
\centering
\caption[Test komparátoru]{Test komparátoru}
\label{ComparatorTest}
\end{figure}
Lze zde pozorovat, jak se jednotlivé částky na sebe namapovaly (označeno šipkou) a jak jsou od sebe vzdáleny (v závorce). Transakce, které se nepodařilo přiřadit, jsou vypsány v části "Major". Ty jsou tedy označeny za neopakující se.
Část, v práci pojmenována jako Datafeeder, vychází z anglických slov \textit{"data"} a \textit{"feeder"} -- v doslovném překladu "data-krmítko". Tato funkcionalita slouží pro načítání dat do neuronové sítě. Je také poměrně jednoduchá. Jako vstupní parametry dostane uživatele, jehož data má načítat počet "\textit{epoch}", které má projít. Epochou se rozumí nějaké časové období, po kterých práci prochází a pro nevelké množství dat je jedna epocha definována jako týden.
Po načtení vstupních parametrů, se vytvoří dotaz do databáze, který načte dvě epochy a pomocí komparátoru doplní označení o opakujících se transakcích (viz. sekce \ref{komparator} Komparátor). Dále data normalizuje a předá neuronové síti, jež tyto transakce postupně po jedné zpracuje.
\subsection{Normalizace dat}\label{normalization}
Pro vyhodnocování neuronovou sítí, je důležité mít data v rozmezí nějakého konstantního intervalu. Pro práci byl konkrétně zvolen ve velikosti <-1,1>. Interval je definován z toho důvodu, že pokud by došlo k jeho překročení některými ze vstupních dat, mohlo by to způsobit "přebíjení" ostatních vah v neuronu. Jinými slovy, výše aktivace neuronu by závisela na několika vstupních datech a ostatní by se ignorovala.
První položkou, která se normalizuje, je datum transakce. Datum sám o sobě není příliš vypovídající, proto by se tato akce dala považovat i za lehké obohacení dat. Pro je normalizaci je totiž využito znalosti, že týden se dělí do sedmi dnů (pondělí - pátek). Z data transakce se tedy zjistí, v který den v týdnu transakce proběhla a zároveň se vytvoří sedm neuronů. Každý z nich bude mít hodnotu 1 nebo -1 (krajní body intervalu), v závislosti, jestli transakce proběhla v ten daný den.
Kupříkladu na vstupu přijde transakce, která proběhla v pondělí. Po normalizaci vznikne šest neuronů, s hodnotou -1, jež jsou obrazem všech dnů v týdnu mimo pondělí a jeden, zobrazující pondělí, jež má hodnotu 1.
Je třeba poznamenat, že hodnota 0 není zvolena záměrně. Uvnitř sítě se jednotlivé vstupy násobí s jednotlivými váhami. Nula není z hlediska násobení neutrální prvek a zároveň při násobení nulou vždy vznikne nula. Tím by došlo k znehodnocení vah a proto je místo nuly zvoleno -1.
\newline
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
Další položkou jsou Konstantní symboly. Konstantní symbol je, obdobně jako datum, číselně další neurčitou položkou. V sekci \ref{ObohaceniDat} Obohacení dat je však rozdělen do jednotlivých kategorií. Ty jsou definovány jako samostatné položky v několika tabulkách databáze. Z toho vychází i způsob implementace - jsou definovány jako výše zmíněný datum. Tedy pro každou položku je vytvořen neuron s hodnotou -1, kromě položek, pod který konstantní symbol spadá. Těm je přiřazena hodnota 1.
\newline
Poslední položka k normalizaci je výška transakce. Správnou hodnotu není lehké určit. Není totiž možné určit maximální velikost transakce. Úvaha pro normalizace byla tedy založena na základě výše škody, dle trestního práva. Z hlediska trestního práva jsou částky rozděleny následovně:
\begin{enumerate}[1)]
\item Škoda nikoli nepatrná – nejméně 5 000 Kč
\item Škoda nikoli malá – nejméně 25 000 Kč
\item Větší škoda – nejméně 50 000 Kč
\item Značná škoda – nejméně 500 000 Kč
\item Škoda velkého rozsahu – nejméně 5 000 000 Kč\cite{velikostSkody}
\end{enumerate}
K rozdělení byla přidána ještě jedna částka 500 Kč. Ta vychází z limitu pro bezkontaktní platby kartou, kdy není třeba zadávat kód PIN.\cite{wirelessLimit}.
Tímto principem zároveň došlo k rozdělení přesně na šest druhů transakcí. Číslo šest je sudé a vzhledem k tomu, že je částky potřeba normalizovat do intervalu <-1,1>, přímo se vybízí rozdělit tyto kategorie na dvě části. Konkrétně 0~--~25~000~Kč v intervalu <-1;0) a vše od 25~000~Kč výše v intervalu (0;1>
Částky jsou však stále vysoké. Pro jejich sníženi bylo tedy třeba využít nějakou funkci, pro jejich zmenšení. K tomu se výborně hodí obdoba aktivační funkce (squashing function) ze sekce \ref{predvidani} Předvídání. Ta částku snižuje na velikost v intervalu (0,1).
Aby byly částky rozděleny do zmíněných šesti kategorií, stačí funkci rozdělit na šestiny, s aktivační funkcí přizpůsobenou jednotlivým částkám. Pro aktivační funkci bylo zvoleno tanh a částky roztaženy na celý interval pomocí "magických konstant" následovně:
\begin{enumerate}[1)]
\item 0 -- 500 Kč
\begin{enumerate}[]
\item $ \frac{tanh(\frac{x}{189})}{3}-1 $
\end{enumerate}
\item 500 -- 5 000 Kč
\begin{enumerate}[]
\item $ \frac{tanh(\frac{x-500}{1889})+1}{3}-1 $
\end{enumerate}
\item 5 000 -- 25 000 Kč
\begin{enumerate}[]
\item $ \frac{tanh(\frac{x-5000}{9446})+2}{3}-1 $
\end{enumerate}
\item 25 000 -- 50 000 Kč
\begin{enumerate}[]
\item $ \frac{tanh(\frac{x-25000}{18892})}{3} $
\end{enumerate}
\item 50 000 -- 500 000 Kč
\begin{enumerate}[]
\item $ \frac{tanh(\frac{x-50000}{188918})+1}{3} $
\end{enumerate}
\item 500 000 -- 5 000 000+ Kč
\begin{enumerate}[]
\item $ \frac{tanh(\frac{x-500000}{1889180})+2}{3} $
\end{enumerate}
\end{enumerate}
Detailní rozložení lze též pozorovat na obr. č. \ref{ExpenseNormalization} Normalizace částky
\begin{figure}
\includegraphics[width=1\textwidth]{img/normalization0-25000.png}
\includegraphics[width=1\textwidth]{img/normalization25000+.png}
\includegraphics[width=1\textwidth]{img/normalizationAll.png}
\centering
\caption[Normalizace částky]{Normalizace částky}
\label{ExpenseNormalization}
\end{figure}
%TODO maybe
%\section{Propojení importů a umělé inteligence}
Databáze by se dala rozdělit na čtyři samostatné celky. Každý celek je ale strukturovaný a propojený s ostatními. Níže jsou všechny popsány i s doprovodnými výřezy diagramu. Kompletní diagram databáze je ale příliš rozsáhlý pro vložení do textu. Je proto přiložen mezi externími přílohami typu \ref{DBdiagram} jako obrázek s názvem \textit{DB\textunderscore diagram.png}.
\subsection{Uživatel}
První částí je ukládání dat o uživateli. Pomyslnou hlavní tabulkou je "User". Obsahuje uživatelská jména registrovaných uživatelů a heslo, které je zahashované a propojené se solí.
Pro každého uživatele si též, v tabulce "Files", ukládá informace, jaké soubory nahrál, resp. jejich jméno a obsah. Je zde ale vystaveno omezení na ukládání souborů tak, aby bylo jejich jméno, v rámci uživatele, unikátní. Omezení bylo vytvořeno z důvodu zabránění nahrávání duplicitních souborů, které je těžké odhalit. Uživatel sice může stále upravit jméno a soubor nahrát, tímto způsobem je ale upozorněn, že už systém data pravděpodobně obsahuje.
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
Další výhoda této tabulky tví v tom, že pokud si uživatel přeje smazat nahraný soubor, jsou známy transakce, které jsou k danému souboru navázány.
\begin{figure}[H]
\includegraphics[width=0.55\textwidth]{img/model-user.jpg}
\centering
\caption[Model databáze - uživatel]{Model databáze - uživatel}
\label{ModelUser}
\end{figure}
\subsection{Transakce}
Další položka databáze jsou jednotlivé transakce. Ty představují pomyslné centrum databáze, protože jsou hlavní informací, od které se veškerá činnost odvíjí. Obsahuje načtená data transakce - datum transakce, částku, poznámku, symboly, účty příjemce i plátce a případný typ transakce.
Dále jsou zde napojeny odkazy na tabulky, zaznamenávající si o jaký typ transakce se jednalo i jaké byl účty příjemce a plátce.
Co se předpovídání opakování týče, v rámci transakce je vytvořen i odkaz na tabulku "Repetition", která označuje transakce, které se opakovaly a nebyly identifikovány za opakující se pomocí neuronové sítě.
\begin{figure}[H]
\centerline{\includegraphics[height=0.65\textwidth]{img/model-transactions.jpg}}
\caption[Model databáze - transakce]{Model databáze - transakce}
\label{ModelTransaction}
\end{figure}
\subsection{Konstantní symbol}
Konstantní symboly v databázi jsou hlavně číselníkem. Slouží k obohacení transakcí a jaký mají význam již bylo zmíněno v sekci \ref{RealizaceObohaceni} Obohacení.
Tato část obsahuje tabulku "ConstantSymbol", což je entita, na kterou je odkazováno z "Transactions". Definuje, jestli případný konstantní symbol, který uživatel vložil je validní. Pokud ano, naváže na sebe jednotlivé číselníky, pro které je symbol definován. Těmito číselníky se rozumí \textit{"Kind"} (druh transakce), \textit{"LastNumber"} (význam poslední číslice), \textit{"MinistryPredefined"} (Předdefinované třídy MFČR) a \textit{"ReservedSymbol"} (Rezervované symboly).
Poslední tabulkou je \textit{"ForeignPayment"}, jež slouží k odlišení zahraničních transakcí.
\begin{figure}[h]
\includegraphics[width=0.55\textwidth]{img/model-KS.png}
\centering
\caption[Model databáze - konstantní symbol]{Model databáze - konstantní symbol}
\label{ModelKS}
\end{figure}
\subsection{Neuronová síť}
Poslední částí databáze je neuronová síť. Slouží k ukládání vypočítaných nastavení, aby natrénovanou síť bylo možné později znovu použít. Systém ukládání funguje dle logiky zmíněné v sekci \ref{ANNexportImport} Export, Import sítě.
V databázi je seznam sítí (\textit{"Network"}). Každá se potom dělí na další podseznamy -- vrstvy (\textit{"Layer"}) a ty dále na neurony (\textit{"Neuron"}). Jako poslední seznam je seznam vah (\textit{"Weights"}) ke korespondujícím neuronům.
\begin{figure}[h]
\includegraphics[width=0.55\textwidth]{img/model-ann.png}
\centering
\caption[Model databáze - neuronová síť]{Model databáze - neuronová síť}
\label{ModelANN}
\end{figure}
\begin{enumerate}
\item vícejádrový výpočet
\item výpočet na grafických kartách
\item větší množství dat (současné je extrémě malé) - ideálně neanonimizovaná
\item zamyslet se nad úpravou minibatche na hodnotu v mocnině 2 (https://www.quora.com/What-is-a-minibatch-in-a-neural-network)
\item v případě obsáhlejších dat lépe rozlišit opakujicí se vs neopakující se transakce
\item doplnit uživatelské označování transakcí za opakující se či nikoliv
\item zvážit patchový a automatizovaný import
\item doporučování produktů na základě předpovědi
\item do webového rozhraní přidat obnovu emailem
\item sepsat UNIT testy
\item přidat do Dockeru
\item přepsat do C/C++ (je rychlejší než C\#), využít C++ knihovny. Kód s velkým množstvím iterací -> vyplatí se investovat do optimalizací.
\item využít jinou knihovnu než Math.NET
\item některé operace jde přepsat do maticových operací (ačkoli na úkor čitelnosti)
\item backpropagation psát cyklem místo rekurze (ačkoli mi rekurze přišla intuitivnější, tak je pomalejší)
\item rozdělení porovnávání na víkendy, svátky, pracovní dny, roční období
\end{enumerate}
\chapter{Závěrečné Testování}
\begin{enumerate}
\item import souborů
\item test api
\item test korektního routování
\item odhlašování/přihlašování uživatele
\item
\chapter{Diskuze}
\begin{enumerate}
\item "zpětný pohled"
\item ukládání do souborů a zachovávání pouze posledních transakcí
\item KS mohly být hardcoded
\end{enumerate}
Pro svou práci jsem si nastudoval syntaxi a použití jazyků, jmenovitě Typescriptu, Angularu a C\# ve spojení z Entity frameworkem, na kterém jsem založil webovou aplikaci jako takovou. Od firmy Trask Solutions a.s. jsem si zajistil data a ty obohatil o druhy konstantních symbolů. Následně jsem na nich učil umělou inteligenci.
V práci se mi nepodařilo umělou umělou inteligenci vytrénovat do té míry, že je schopna předpovědět chování uživatelů. To bylo způsobeno buď nedostatečným množstvím dat pro trénování anebo chybou v implementaci.
Jako možná další možné vylepšení bych uvedl analýzu transakčních poznámek. Toto by šlo implementovat pravděpodobně nejlépe rozhodovacím stromem. V případě přístupu k neanonymizovaným datům, by se daly doplnit další možné souvislosti pro učení umělé inteligence. Protože je aplikace nezávislá, tak by pro pohodlí uživatelů byla také vhodná nějaká forma automatického importu transakcí (například formou pravidelného zasílání emailů do aplikace).
\end{conclusion}
\bibliographystyle{csn690}
\bibliography{mybibliographyfile}
\appendix
%============= seznam zkratek disabled ===================
\chapter{Seznam použitých zkratek}
%\printglossaries
\begin{description}
\item [JSON] JavaScript Object Notation
\item [JWT] JSON Web Token
\item [SQL] Structured Query Language
\item [NoSQL] non SQL
\item [CSRF] Cross-site request forgery
\item [ARES] Administrativní registr ekonomických subjektů
\item [XOR] Exkluzivní disjunkce
\item [CSV] Comma-separated values
\item [KS] konstantní symbol
\item [VS] variabilní symbol
\item [SS] specifický symbol
\item [API] Application Programming Interface
\item [HTTP] Hypertext Transfer Protocol
\item [ID] identifikátor
\item [MFČR] Ministerstvo financí České Republiky
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
% % % % % % % % % % % % % % % % % % % % % % % % % % % %
% % Tuto kapitolu z výsledné práce ODSTRAŇTE.
% % % % % % % % % % % % % % % % % % % % % % % % % % % %
%
% \chapter{Návod k~použití této šablony}
%
% Tento dokument slouží jako základ pro napsání závěrečné práce na Fakultě informačních technologií ČVUT v~Praze.
%
% \section{Výběr základu}
%
% Vyberte si šablonu podle druhu práce (bakalářská, diplomová), jazyka (čeština, angličtina) a kódování (ASCII, \mbox{UTF-8}, \mbox{ISO-8859-2} neboli latin2 a nebo \mbox{Windows-1250}).
%
% V~české variantě naleznete šablony v~souborech pojmenovaných ve formátu práce\_kódování.tex. Typ může být:
% \begin{description}
% \item[BP] bakalářská práce,
% \item[DP] diplomová (magisterská) práce.
% \end{description}
% Kódování, ve kterém chcete psát, může být:
% \begin{description}
% \item[UTF-8] kódování Unicode,
% \item[ISO-8859-2] latin2,
% \item[Windows-1250] znaková sada 1250 Windows.
% \end{description}
% V~případě nejistoty ohledně kódování doporučujeme následující postup:
% \begin{enumerate}
% \item Otevřete šablony pro kódování UTF-8 v~editoru prostého textu, který chcete pro psaní práce použít -- pokud můžete texty s~diakritikou normálně přečíst, použijte tuto šablonu.
% \item V~opačném případě postupujte dále podle toho, jaký operační systém používáte:
% \begin{itemize}
% \item v~případě Windows použijte šablonu pro kódování \mbox{Windows-1250},
% \item jinak zkuste použít šablonu pro kódování \mbox{ISO-8859-2}.
% \end{itemize}
% \end{enumerate}
%
%
% V~anglické variantě jsou šablony pojmenované podle typu práce, možnosti jsou:
% \begin{description}
% \item[bachelors] bakalářská práce,
% \item[masters] diplomová (magisterská) práce.
% \end{description}
%
% \section{Použití šablony}
%
% Šablona je určena pro zpracování systémem \LaTeXe{}. Text je možné psát v~textovém editoru jako prostý text, lze však také využít specializovaný editor pro \LaTeX{}, např. Kile.
%
% Pro získání tisknutelného výstupu z~takto vytvořeného souboru použijte příkaz \verb|pdflatex|, kterému předáte cestu k~souboru jako parametr. Vhodný editor pro \LaTeX{} toto udělá za Vás. \verb|pdfcslatex| ani \verb|cslatex| \emph{nebudou} s~těmito šablonami fungovat.
%
% Více informací o~použití systému \LaTeX{} najdete např. v~\cite{wikilatex}.
%
% \subsection{Typografie}
%
% Při psaní dodržujte typografické konvence zvoleného jazyka. České \uv{uvozovky} zapisujte použitím příkazu \verb|\uv|, kterému v~parametru předáte text, jenž má být v~uvozovkách. Anglické otevírací uvozovky se v~\LaTeX{}u zadávají jako dva zpětné apostrofy, uzavírací uvozovky jako dva apostrofy. Často chybně uváděný symbol "{} (palce) nemá s~uvozovkami nic společného.
%
% Dále je třeba zabránit zalomení řádky mezi některými slovy, v~češtině např. za jednopísmennými předložkami a spojkami (vyjma \uv{a}). To docílíte vložením pružné nezalomitelné mezery -- znakem \texttt{\textasciitilde}. V~tomto případě to není třeba dělat ručně, lze použít program \verb|vlna|.
%
% Více o~typografii viz \cite{kobltypo}.
%
% \subsection{Obrázky}
%
% Pro umožnění vkládání obrázků je vhodné použít balíček \verb|graphicx|, samotné vložení se provede příkazem \verb|\includegraphics|. Takto je možné vkládat obrázky ve formátu PDF, PNG a JPEG jestliže používáte pdf\LaTeX{} nebo ve formátu EPS jestliže používáte \LaTeX{}. Doporučujeme preferovat vektorové obrázky před rastrovými (vyjma fotografií).
%
% \subsubsection{Získání vhodného formátu}
%
% Pro získání vektorových formátů PDF nebo EPS z~jiných lze použít některý z~vektorových grafických editorů. Pro převod rastrového obrázku na vektorový lze použít rasterizaci, kterou mnohé editory zvládají (např. Inkscape). Pro konverze lze použít též nástroje pro dávkové zpracování běžně dodávané s~\LaTeX{}em, např. \verb|epstopdf|.
%
% \subsubsection{Plovoucí prostředí}
%
% Příkazem \verb|\includegraphics| lze obrázky vkládat přímo, doporučujeme však použít plovoucí prostředí, konkrétně \verb|figure|. Například obrázek \ref{fig:float} byl vložen tímto způsobem. Vůbec přitom nevadí, když je obrázek umístěn jinde, než bylo původně zamýšleno -- je tomu tak hlavně kvůli dodržení typografických konvencí. Namísto vynucování konkrétní pozice obrázku doporučujeme používat odkazování z~textu (dvojice příkazů \verb|\label| a \verb|\ref|).
%
% \begin{figure}\centering
% \includegraphics[width=0.5\textwidth, angle=30]{cvut-logo-bw}
% \caption[Příklad obrázku]{Ukázkový obrázek v~plovoucím prostředí}\label{fig:float}
% \end{figure}
%
% \subsubsection{Verze obrázků}
%
% % Gnuplot BW i barevně
% Může se hodit mít více verzí stejného obrázku, např. pro barevný či černobílý tisk a nebo pro prezentaci. S~pomocí některých nástrojů na generování grafiky je to snadné.
%
% Máte-li například graf vytvořený v programu Gnuplot, můžete jeho černobílou variantu (viz obr. \ref{fig:gnuplot-bw}) vytvořit parametrem \verb|monochrome dashed| příkazu \verb|set term|. Barevnou variantu (viz obr. \ref{fig:gnuplot-col}) vhodnou na prezentace lze vytvořit parametrem \verb|colour solid|.
%
% \begin{figure}\centering
% \includegraphics{gnuplot-bw}
% \caption{Černobílá varianta obrázku generovaného programem Gnuplot}\label{fig:gnuplot-bw}
% \end{figure}
%
% \begin{figure}\centering
% \includegraphics{gnuplot-col}
% \caption{Barevná varianta obrázku generovaného programem Gnuplot}\label{fig:gnuplot-col}
% \end{figure}
%
%
% \subsection{Tabulky}
%
% Tabulky lze zadávat různě, např. v~prostředí \verb|tabular|, avšak pro jejich vkládání platí to samé, co pro obrázky -- použijte plovoucí prostředí, v~tomto případě \verb|table|. Například tabulka \ref{tab:matematika} byla vložena tímto způsobem.
%
% \begin{table}\centering
% \caption[Příklad tabulky]{Zadávání matematiky}\label{tab:matematika}
% \begin{tabular}{|l|l|c|c|}\hline
% Typ & Prostředí & \LaTeX{}ovská zkratka & \TeX{}ovská zkratka \tabularnewline \hline \hline
% Text & \verb|math| & \verb|\(...\)| & \verb|$...$| \tabularnewline \hline
% Displayed & \verb|displaymath| & \verb|\[...\]| & \verb|$$...$$| \tabularnewline \hline
% \end{tabular}
% \end{table}
%
% % % % % % % % % % % % % % % % % % % % % % % % % % % %
%============================== temporary disabled =======================
\chapter{Přiložené soubory}
\begin{description}
\item [KB\textunderscore ARES.xml] Výpis z ARES (Komerční banka)
\item [DB\textunderscore diagram.png] Kompletní diagram datového modelu\label{DBdiagram}
\begin{figure}
\dirtree{%
.1 readme.txt\DTcomment{stručný popis obsahu CD}.
%.1 exe\DTcomment{adresář se spustitelnou formou implementace}.
%TODO přemístit do adresáře implementace
.1 src.\DTcomment{zdrojové kódy implementace}.%
.2 bin.
.3 x64.
.4 Debug.
.5 netcoreapp2.2.
.6 publish\DTcomment{adresář se spustitelnou formou implementace}.
%.2 impl\DTcomment{zdrojové kódy implementace}.
.2 Recommender.bak\DTcomment{Databáze se základními daty}.
.2 BP\textunderscore Radek\textunderscore Pus\textunderscore 2019.tex\DTcomment{zdrojová forma práce ve formátu \LaTeX{}}.
.2 BP\textunderscore Radek\textunderscore Pus\textunderscore 2019.pdf\DTcomment{text práce ve formátu PDF}.
.1 Přílohy\DTcomment{Přiložené soubory (Příloha B)}.
%.2 thesis.ps\DTcomment{text práce ve formátu PS}.