magisterka/rozdzial_2.tex
2018-03-12 23:12:25 +01:00

323 lines
19 KiB
TeX
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\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}