\chapter{Metody ekstrakcji informacji}
% w kontekście mojego projektu
W tym rozdziale zaprezentowane są wybrane metody,
które brane były pod uwagę lub zostały zastosowane
w opisywanym tutaj systemie ekstrakcji informacji o godzinach rozpoczęcia mszy świętych.
\section {Algorytmy \textit{bootstraping}}
Niech $J$ będzie dowolną reprezentacją języka (wyraz, fraza, wyrażenie
regularne itp.).
W dziedzinie przetwarzania języka naturalnego \textit{bootstraping} to technika
wyszukiwania niezanotowanych (nieprzypisanych do badanej klasy) $J$ przy użyciu małego zbioru specjalnie
wyselekcjonowanych zanotowanych $J$.
Implementacji algorytmu \textit{bootstraping} jest wiele, wszystkie jednak
oparte są na następującym schemacie \cite{Bootstrap}:
\enlargethispage{4\baselineskip}
\begin{enumerate}
\item Stwórz pustą listę reprezentacji języka $J$. % pusta lista $J$, pusta lista wyrazów, pusta
                              % lista fraz
\item Zainicjalizuj listę starannie dobranymi $J$.
\item Wykorzystaj elementy listy do znalezienia nowych $J$ z korpusu treningowego.
\item Oceń nowe $J$; najlepsze $J$ dodaj do listy.
\item Wróć do 3. i powtarzaj aż do osiągnięcia z góry określonej liczby iteracji
  \newline lub
  spełnienia innego warunku stopu.

\end{enumerate}
% \textit{Bootstraping} jest szczególnie przydatny w przypadku, gdy mamy mały
% zbiór treningowy, ponieważ z jego pomocą jesteśmy w stanie powiększyć zbiór
% treningowy. %todo poprawić


\subsection{Wzorce Hearst}
Jednymi z pierwszych implementacji algorytmu \textit{bootstraping} w dziedzinie
ekstrakcji informacji
są wzorce Hearst \textit{(ang. Hearst patterns)} \cite{Hearst}.

\smallskip
\noindent Znajdowanie nowych przykładów uczących za pomocą wzorców Hearst przedstawia się
następująco:

\begin{enumerate}
\item Wybierz relację leksykalną $R$.
\item Utwórz początkowy zbiór $S$ par $(x, y)\in R$, gdzie $x$ i $y$ to słowa lub frazy.
\item Znajdź zdania, które zawierają pary ze zbioru $S$.
\item Przyjrzyj się kontekstowi, w jakim występują te pary. Załóż, że często powtarzające się wzorce reprezentują relację R.
\item Wykorzystaj nowo odkryte wzorce do znalezienia kolejnych par $(x, y)\in R$.
\item Dodaj nowo znalezione pary do zbioru $S$, wróć do 3. i powtarzaj aż do osiągnięcia z góry określonej liczby iteracji.
\end{enumerate}

\enlargethispage{4\baselineskip}
\subsubsection{Przykład}
Rozważmy relację R taką, że $(x, y) \in R$ wtedy, gdy $x$ został pochowany w
$y$.
Załóżmy, że zaczynamy z parą \texttt{('Józef Piłsudski', 'Kraków')}$\in R$.
W korpusie treningowym szukamy zdań zawierających w sobie parę \texttt{('Józef
  Piłsudski', 'Kraków')} i otrzymujemy zdania takie jak:

\centerline{„Józef Piłsudski został pochowany w Krakowie.”}
\centerline{„Miejsce pochówku Józefa Piłsudskiego to Kraków.”}
\centerline{„Grób Józefa Piłsudskiego znajduje się w Krakowie.”}

\noindent Ze znalezionych zdań tworzymy następujące wzorce:

\centerline{$x$ został pochowany w $y$.}
\centerline{Miejsce pochówku $x$ to $y$.}
\centerline{Grób $x$ znajduje się w  $y$.}

\noindent Wykorzystujemy powyższe wzorce do znalezienia nowych par będących w relacji $R$, przykładowo:
% i otrzymujemy:

\centerline{\texttt{('Witold Doroszweski, 'Warszawa')}}
\centerline{\texttt{('Jana Długosz', 'Zakopane')}}

\noindent Następnie szukamy zdań w których występują powyższe pary, na przykład:

\centerline{„Witold Doroszewski spoczywa w Warszawie.”}
\centerline{„Na cmentarzu w Zakopanem mieści
  się grób Jana Długosza.”}

\noindent Z nowo otrzymanych zdań tworzymy poniższe wzorce:

\centerline{$x$ spoczywa w $y$.}
\centerline{Na cmentarzu w $y$ mieści się grób $x$.}

\noindent Powtarzamy powyższy algorytm aż do osiągnięcia określonej liczby iteracji.


% \subsection{Miejsce na opis bardziej skomplikowanej metody implementującej
  % algorytm \textit{bootstraping}}

\section{Automatyczne generowanie wyrażeń regularnych za pomocą algorytmów genetycznych}
W 2015 roku Bartoli i in. zaprezentowali efektywny algorytm genetyczny do generowania
wzorców zapisanch w
postaci wyrażeń regularnych przy użyciu niewielkiego zbioru zanotowanych
przykładów (fraz oznaczonych jako pasujące do wyrażeń regularnych) \cite{genetic}. Nowością było zastosowanie metody „dziel i zwyciężaj”.
Zamiast uczyć się jednego wyrażenia regularnego, które znajdowałoby wszystkie
przykłady, system uczy się wielu różnych wzorców, które dopiero po połączeniu
alternatywą tworzą
ostateczne wyrażenie regularne.
% Problem automatycznego generowania wyrażeń regularnych jest złożony. Warto zauważyć, że % bardzo łatwo wytrenować na zbiorze treningowym system, który znajdzie wzorzec o bardzo wysokiej precyzji i niskiej % czułości (np. wystarczy alternatywa, której składnikami są wszystkie zanotowane przykłady), ale szczególnie trudno wytrenować system tak, aby generalizował się na przypadki poza % zbiorem treningowym (innymi słowy taki system łatwo przetrenować). %(otrzymali wyniki bardzo zadowalające wyniki ) tabela wyników
\subsection{Opis problemu}
Niech $x_s$ będzie spójnym podciągiem ciągu znaków $s$ reprezentowanym przez
indeks początkowy i końcowy w $s$. Dla ułatwienia, w przykładach $x_s$ będziemy
reprezentować przez zawartość i indeks początkowy.
\enlargethispage{1\baselineskip}
Na przykład $x_s=\texttt{ku}_0$, $x'_s=\texttt{ku}_2$, $x''_s=\texttt{kuku}_0$, $x'''_s=\texttt{łka}_4$ to spójne podciągi ciągu znaków $s=\texttt{kukułka}$.
$x_s$ nazywa się nadłańcuchem $x'_s$ (a $x'_s$ jest podłańcuchem $x_s$),
jeśli (i) $x'_s$ jest krótszy niż $x_s$, (ii) indeks początkowy $x'_s$ jest
nie mniejszy niż indeks początkowy $x_s$ oraz (iii) indeks końcowy $x'_s$
jest nie większy niż indeks końcowy $x_s$. Na przykład $\texttt{ku}_0$
jest podłańcuchem $\texttt{kuku}_0$.
Mówi się, że $x_s$ nachodzi na $x'_s$ (lub $x'_s$ nachodzi na $x_s$), jeśli (i) indeks początkowy $x_s$ jest
nie większy niż indeks końcowy $x'_s$ oraz (ii) indeks końcowy $x_s$ jest nie
mniejszy niż indeks początkowy $x'_s$.

Niech $(s,X)$ będzie przykładem uczącym, w którym $X$ to zbiór
  nienachodzących na siebie $x_s$.

Jako $e(s,P)$ oznacza się zbiór wszystkich ciągów $x_s$
wyekstrahowanych poprzez zbiór wyrażeń regularnych $P$, taki że (i)
$x_s$
pasuje do jakiegokolwiek wyrażenia regularnego $p\in P$, (ii) każdy nadłańcuch
$x'_s$ ciągu $x_s$ nie pasuje do żadnego wyrażenia regularnego $p\in P$
oraz (iii) dla każdego ciągu $x''_s\neq x_s$, który nachodzi na
$x_s$, indeks początkowy $x''_s$ jest większy od indeksu początkowego $x_s$
albo $x''_s$ nie pasuje do żadnego $p\in P$.
Między innymi dla $s=\texttt{abcde}\textvisiblespace \texttt{a}$ i
$P=\{\texttt{a}, \texttt{bc}, \texttt{cde}, \texttt{de}\}$
$e(s,P)=\{a_0, a_6, bc_1\}$. Należy zwrócić uwagę, że $de_3 \notin e(s,P)$ i $cde_2 \notin e(s,P)$, ponieważ nie spełniają one kolejno warunków (ii) oraz (iii).

Mając dwa zbiory anotowanych przykładów $(E, E')$, zbiór wyrażeń
regularnych $P$ generowany jest używając
tylko i wyłącznie $E$ w taki sposób, że (i) maksymalizowana jest średnia harmoniczna z precyzji i
pokrycia (ang. \textit{recall}) na $E'$ oraz (ii) minimalizowana jest $\sum_{p\in
  P}{l(p)}$, gdzie $l(p)$ to długość wyrażenia regularnego $p$.
Wtedy precyzja i pokrycie definiowane są w następujący sposób:

$$Prec(P, E'):=\frac{\sum_{(s,X)\in E'}{|e(s,P) \cup X|}}{\sum_{(s,X)\in E'}{|e(s,P)|}}$$
$$Rec(P, E'):=\frac{\sum_{(s,X)\in E'}{|e(s,P) \cup X|}}{\sum_{(s,X)\in E'}{|X|}}$$

\subsection{Szczegóły algorytmu genetycznego}

Na wejściu do algorytmu genetycznego podawany jest zbiór treningowy $T$, a na
wyjściu otrzymuje się pojedyncze wyrażenie regularne $p$.
Zbiór treningowy $E$ składa się z trójki uporządkowanej $(s,X_d,X_u)=(s,X)$,
gdzie $X_d$ to zbiór pożądanych ciągów $x_s$ ekstrahowanych przez $p$, a
$X_u$ to zbiór niepożądanych ciągów $x_s$ ekstrahowanych przez $p$.
Nie istnieje żaden podłańcuch $x'_s$ ciągu $x_s \in
X_d$, który nachodzi na jakikolwiek podłańcuch $x'''_s$ ciągu $x''_s \in X_u$.

Wyrażenie regularne reprezentowane jest za pomocą drzewa. Liście składają
się z:
\begin{enumerate}
\item zakresów znaków np. \texttt{a-ż}, \texttt{A-Ż} i \texttt{0-9},
\item klas znaków \texttt{\textbackslash w} i \texttt{\textbackslash d},
\item cyfr od 0 do 9,
\item częściowych zakresów, czyli największego zakresu znaków występującego \newline
  w $\bigcup_{(s,X_d,X_u)\in T}X_d$, np. dla $\texttt{\{pokój}_3, \texttt{ubierać}_{13}\}$
  otrzymuje się
  zakresy \newline \texttt{j-k} i \texttt{o-r} (przy założeniu, że
  korzysta się z polskiego alfabetu),
\item znaków specjalnych takich jak np. \texttt{\textbackslash ., :, @}.
\end{enumerate}
Wierzchołki nie będące liściami składają się z:
\begin{enumerate}
\item konkatenacji $\bullet \bullet$,
\item klasy znaków $[\bullet]$ i jej negacji $[ \hat{\ } \bullet ]$,
\item kwantyfikatorów bez nawrotów (ang. possessive quantifiers) $\bullet
  \ast$\texttt{+}, $\bullet$\texttt{++}, $\bullet$\texttt{?+ } oraz  $ \bullet
  \{ \bullet, \bullet \}$\texttt{+},
\item oznaczeń grup nieprzechwytujących \texttt{(?:$\bullet$)}.
\end{enumerate}
Wyrażenie regularne $p$ otrzymuje się przechodząc drzewo sposobem
\textit{post-order},\newline w którym pod znak $\bullet$ w wierzchołkach
niebędących
liściami podstawia się łańcuchy znaków zawarte w dzieciach tego wierzchołka.

\begin{figure}[tbh]
\centering
\includegraphics[width=0.7\hsize]{drzewo.png}
\caption{Reprezentacja wyrażenia regularnego \texttt{abc\{1,2\}+} za pomocą drzewa.}
\label{drzewo_pic}
\end{figure}

\subsubsection{Inicjalizacja populacji}
Jako $n_{pop}$ oznacza się rozmiar populacji wyrażeń regularnych $P$. Dla każdego $x_s\in \bigcup_{(s,X_d,X_u)\in T}X_d$ budowane są dwa osobniki
(osobnikiem jest wyrażenie regularne). Pierwszy osobnik tworzony jest z $x_s$, w którym każda cyfra zamieniana
jest na \texttt{\textbackslash d} oraz każda litera zamienia jest na
\texttt{\textbackslash w}. Drugi osobnik tworzony jest identycznie jak pierwszy
z tą różnicą, że wielkrotne wystąpienia \texttt{\textbackslash d} (lub
\texttt{\textbackslash w}) zastępuje się oznaczeniami \texttt{\textbackslash d++} (lub
\texttt{\textbackslash w++}). W szczególności dla $x_s=\texttt{14\textvisiblespace lutego}$
otrzymujemy osobniki \texttt{\textbackslash d\textbackslash d\textvisiblespace
  \textbackslash w\textbackslash w\textbackslash w\textbackslash w\textbackslash
  w\textbackslash w} oraz
\texttt{\textbackslash d++\textvisiblespace \textbackslash w++}.

Jeśli liczba wygenerowanych osobników jest większa niż $n_{pop}$, to są one
losowo usuwane, natomiast jeśli liczba osobników jest mniejsza niż $n_{pop}$, to
brakujące osobniki są generowane metodą \textit{Ramped half-and-half} \cite{ramped}. Osobniki
niereprezentujące poprawnego wyrażenia regularnego są odrzucane, a w ich miejsce
generowane \newline są nowe.

\subsubsection{Funkcja przystosowania}
Dla każdego osobnika funkcję przystosowania defniuje się jako:
$$f(p):=(Prec(p,T), Acc(p,T), l(p))$$
Wprowadza się również dwie nowe operacje $\sqcap$ i $\ominus$, na których oparte są
funkcje $Prec$ i $Acc$.
Zakłada się, że $X_1$ i $X_2$ to zbiory spójnych podciągów tego samego łańcucha znaków $s$.
Wtedy:
\begin{itemize}
\item $X_1 \ominus X_2$ jest zbiorem takich $x_s$, że
(i) są one spójnym podciągiem jakiegoś elementu $X_1$, (ii) nie
nachodzą na żaden z elementów $X_2$ oraz (iii) nie mają nadłańcucha, który
spełnia warunki
(i), (ii);
\item $X_1 \sqcap X_2$ jest zbiorem takich $x_s$, że (i) są one
 spójnym podciągiem jakiekolwiek elementu $X_1$ i
 jakiekolwiek elementu $X_2$ oraz (ii) nie mają nadłańcucha, który spełnia (i).
\end{itemize}

Między innymi dla $X_1=\{\texttt{Ja}_0, \texttt{ty}_4,
\texttt{Adam\textvisiblespace Małysz}_9\}$, $X_2=\{\texttt{Ja}_0,
\texttt{Małysz}_{14}\}$: \newline $X_1 \ominus X_2 = \{\texttt{ty}_4, \texttt{Adam\textvisiblespace}_{9}\}$,
$X_1 \sqcap X_2 = \{\texttt{Ja}_0,\texttt{Małysz}_{14}\}$.

\enlargethispage{4\baselineskip}
\bigskip
\noindent W końcu $$Prec(p,T):=\frac{\sum_{(s,X_d,X_u)\in T}|e(s,\{p\})\cap
  X_d|}{\sum_{(s,X_d,X_u)\in T}|e(s,\{p\})\sqcap (X_d \cup X_u)|}$$
Drugi element trójki uporządkowanej, czyli $Acc(p,T)$ jest średnią arytmetyczną
pokrycia na znakach (ang. True Positive Character Rate skr. TPCR) i
specyficzności na znakach (ang. True Negative Character Rate skr. TNCR):
\begin{equation*}
  \begin{split}
    TPCR(p,T) & :=\frac{\sum_{(s,X_d,X_u)\in T}||e(s,\{p\})\sqcap X_d||}{\sum_{(s,X_d,X_u)\in T}||X_d||} \\[3pt]
    TNCR(p,T) & :=\frac{\sum_{(s,X_d,X_u)\in T}||s \ominus e(s,\{p\}) \sqcap X_u||}{\sum_{(s,X_d,X_u)\in T}||X_u||} \\[3pt]
    Acc(p,T) & :=\frac{TPCR(p,T) + TNCR(p,T)}{2}
  \end{split}
\end{equation*}
gdzie $||X|| = \sum_{x_s\in X}l(x_s)$, a $l(x_s)$ oznacza długość ciągu $x_s$.

Osobniki porównywane są w pierwszej kolejności na podstawie $Prec$, \newline potem
za pomocą $Acc$, a na końcu w przypadku identycznych
$Prec$ i $Acc$ brane jest pod uwagę $l(p)$.

\enlargethispage{4\baselineskip}
%   \end{split}
% \end{equation*}
% \begin{equation*}
%  \begin{split}
\textbf{Przykład}
\begin{equation*}
 \begin{split}
   s & = \texttt{70.\textvisiblespace Poprawny\textvisiblespace zapis\textvisiblespace dat\textvisiblespace to\textvisiblespace np.\textvisiblespace } \\
     & \quad \; \texttt{10.04.2019,\textvisiblespace 1.03.2018\textvisiblespace (nie\textvisiblespace 01.03.2018).} \\
 X_d & =\{\texttt{10.04.2019}_{30}, \texttt{1.03.2018}_{42}\} \\
 X_u & = \{\texttt{70.\textvisiblespace Poprawny\textvisiblespace zapis\textvisiblespace dat\textvisiblespace to\textvisiblespace np.\textvisiblespace }_0, \texttt{\textvisiblespace (nie\textvisiblespace}_{52}, \;\texttt{).}_{67}\} \\
 T & = \{(s, X_d, X_u)\} \\
 p_1 & = \texttt{\textbackslash d\{2,2\}+.\textbackslash d\{2,2\}+.\textbackslash d\{4,4\}+.} \\
 p_2 & = \texttt{\textbackslash d\{2,4\}+} \\
 e(s, {p_1}) & = \{\texttt{10.04.2019}_{30}, \texttt{01.03.2018}_{57}\} \\
 e(s, {p_2}) & = \{\texttt{70}_{0}, \texttt{10}_{30}, \texttt{04}_{33}, \texttt{2019}_{36}, \texttt{03}_{44}, \texttt{2018}_{47}, \texttt{01}_{57}, \texttt{03}_{60}, \texttt{2018}_{63}\} \\[3pt]
 Prec(p_1, T) & = \frac{|\{\texttt{10.04.2019}_{30}\}|}{|\{\texttt{10.04.2019}_{30}\}|} =\frac{1}{1} = 1 \\[3pt]
 Prec(p_2, T) & = \frac{|\emptyset|}{|\{\texttt{70}_{0}, \texttt{10}_{30}, \texttt{04}_{33}, \texttt{2019}_{36}, \texttt{03}_{44}, \texttt{2018}_{47}\}|} = \frac{0}{6} = 0 \\[4pt]
 TPCR(p_1, T) & = \frac{||\{\texttt{10.04.2019}_{30}\}||}{||\{\texttt{10.04.2019}_{30}, \texttt{1.03.2018}_{42}\}||} = \frac{10}{19} \\[4pt]
 TPCR(p_2, T) & = \frac{||\{\texttt{10}_{26}, \texttt{04}_{29}, \texttt{2019}_{32}, \texttt{03}_{40}, \texttt{2018}_{43}\}||}{||\{\texttt{10.04.2019}_{30}, \texttt{1.03.2018}_{42}\}||} = \frac{14}{19} \\[4pt]
 TNCR(p_1, T) & = \frac{||\{\texttt{70.\textvisiblespace  Poprawny\textvisiblespace zapis\textvisiblespace dat\textvisiblespace to\textvisiblespace np.\textvisiblespace }_0, \texttt{\textvisiblespace (nie\textvisiblespace}_{51}, \;\texttt{).}_{67}\}||}{||\{\texttt{70.\textvisiblespace  Poprawny\textvisiblespace zapis\textvisiblespace dat\textvisiblespace to\textvisiblespace np.\textvisiblespace }_0, \texttt{\textvisiblespace (nie\textvisiblespace}_{51}, \;\texttt{).}_{67}\}||} = \frac{38}{38} = 1\\[4pt]
 TNCR(p_2, T) & = \frac{||\{\texttt{.\textvisiblespace  Poprawny\textvisiblespace zapis\textvisiblespace dat\textvisiblespace to\textvisiblespace np.\textvisiblespace }_2, \texttt{\textvisiblespace (nie\textvisiblespace}_{51}, \;\texttt{).}_{67}\}||}{||\{\texttt{70.\textvisiblespace  Poprawny\textvisiblespace zapis\textvisiblespace dat\textvisiblespace to\textvisiblespace np.\textvisiblespace }_0, \texttt{\textvisiblespace (nie\textvisiblespace}_{51}, \;\texttt{).}_{67}\}||} = \frac{36}{38}\\[4pt]
 f(p_1) & = \bigg(1, 0.76=\frac{1}{2}\Big(\frac{10}{19} + 1\Big), 20 \bigg)\\
 f(p_2) & = \bigg(0, 0.84=\frac{1}{2}\Big(\frac{14}{19} + \frac{36}{38}, \Big), 24\bigg)
 \end{split}
\end{equation*}
Zgodnie z wprowadzoną funkcją oceny osobnik $p_1$ jest lepiej
przystosowany niż osobnik $p_2$.

\subsubsection{Ewolucja populacji}
Populacja $P$ o liczności $n_{pop}$ ewoluuje następująco. W każdej epoce $0.1n$ osobników
generowanych jest losowo za pomocą metody
\textit{Ramped half-and-half} \cite{ramped}, kolejne $0.1n$ osobników powstaje za pomocą mutacji, a
pozostałe $0.8n$ otrzymuje \newline się metodą krzyżowania.
Z populacji P i zbioru nowo
wygenerowanych osobników wybierane jest $n$ najlepiej przystosowanych osobników,
które tworzą nową populację. Osobniki wybierane są do mutacji i krzyżowania
metodą turnieju (losowanie z $P$ siedmiu osobników i wyłonienie najlepszego).
Pondato wymusza się także różnorodność między fenotypami osobników, tzn. jeśli oba
osobniki mają identyczny łańcuch znaków to w populacji zostawia się tylko jednego
z nich. Koniec iteracji następuje, gdy zostanie osiągnięty z góry ustalony limit
iteracji lub
najlepiej przystosowany osobnik nie zmieni się od określonej liczby epok.
Finalne wyrażenie regularne $p$ to najlepiej przystosowany osobnik po
zakończeniu wszystkich iteracji.
\subsubsection{Zastosowanie metody „dziel i zwyciężaj”}
Zbiór wyrażeń regularnych $P$ generowany jest za pomocą strategii „dziel i zwyciężaj”.
W każdej iteracji spójne podciągi ciągu znaków $s$, które zostały poprawnie
wykryte przez $P$ są usuwane ze zbioru treningowego.

\enlargethispage{2\baselineskip}
Oby uniknąć przetrenowania, czyli bardzo wysokiego \textit{F-measure} na $E$, a niskiego na $E'$,
zbiór treningowy $E$ dzielony jest losowo na dwa zbiory $E_{train}$ i $E_{validation}$
takie, że $E=E_{train} \cup E_{validation}$, $E_{train} \cap E_{validation} =
\emptyset$ \newline i
$\sum_{(s,X)\in E_{train}}|X|\approx \sum_{(s,X)\in E_{validation}}|X|$.


\noindent Procedura generowania zbioru wyrażeń regularnych $P$ prezentuje się następująco.

Zacznij z $P=\emptyset$ i z $T$ utworzonym w taki sposób, że dla
każdego $(s,X)\in E_{train}$, trójka uporządkowana $(s, X, \{s\} \ominus X)$ jest
dodawana do $T$, \newline gdzie $X_d:=X$ i $X_u:=\{s\} \ominus X$.

\noindent Następnie dopóki $\bigcup_{(x,X_d,X_u)\in T}X_d\ne \emptyset$ powtarzaj:
\begin{enumerate}
\item Wykonaj algorytm genetyczny na $T$ i otrzymaj wyrażenie regularne $p$.
\item Jeśli $Prec(p,T)=1$, to $P:=P\cup\{p\}$, w przeciwnym wypadku przerwij pętlę.
\item Dla każdego $(s, X_d, X_u)\in T$ ustaw $X_d:=X_d\setminus e(s, \{p\})$.
\end{enumerate}

Powyższa procedura powtarzana jest wiele razy z różnym zarodkiem generatora
liczb losowych (startowy zbiór trenujący $T$ pozostaje bez zmian), by otrzymać
dużo różnych zbiorów $P$, z których na końcu wybierany jest ten o najwyższej
 średniej harmonicznej z precyzji i pokrycia na $E=E_{train} \cup E_{validation}$.
\section{Sieci neuronowe}
