diff --git a/abstract.tex b/abstract.tex
index ca428a5..0594b39 100644
--- a/abstract.tex
+++ b/abstract.tex
@@ -1,4 +1,10 @@
\chapter*{Abstract}
-todo
+The thesis presents the process of creating a system for extracting information
+about opening hours
+of holy masses. The methods of collecting data of Polish parishes are being
+described, especially the process of creating spiders. Then two methods are shown
+for the extraction of opening hours of masses: a rule-based method and
+machine learning-based method. More attention is devoted to machine
+learning-based method that uses a text classifier.
-\textbf{Key words:} information extraction
\ No newline at end of file
+\textbf{Key words:} information extraction, web spidering, text classification
\ No newline at end of file
diff --git a/bibliografia.bib b/bibliografia.bib
index dcbcc6b..61bba1e 100644
--- a/bibliografia.bib
+++ b/bibliografia.bib
@@ -1,66 +1,98 @@
-@ARTICLE{Bootstrap,
- author = {Daniel Waegel},
- title = {A Survey of Bootstrapping Techniques in Natural Language Processing},
- journal = {Department of Computer Science,
-University of Delaware, Literature Survey Reports},
- year = {2013}
-}
-
-@ARTICLE{Hearst,
- author = {Marti Hearst },
- title = {Automatic Acquisition of Hyponyms from Large Text Corpora.},
- journal = {Proc. of the
-Fourteenth International Conference on Computational Linguistics, Nantes, France.},
- year = {1992}
-}
-
-
-@inproceedings{genetic,
- title={Learning text patterns using separate-and-conquer genetic programming},
- author={Bartoli, Alberto and De Lorenzo, Andrea and Medvet, Eric and Tarlao, Fabiano},
- booktitle={European Conference on Genetic Programming},
- pages={16--27},
- year={2015},
- organization={Springer}
-}
-
-@article{ramped,
- title={Genetic programming as a means for programming computers by natural selection},
- author={Koza, John R},
- journal={Statistics and computing},
- volume={4},
- number={2},
- pages={87--112},
- year={1994},
- publisher={Springer}
-}
-
-
@article{gus,
title={Rocznik statystyczny Rzeczypospolitej Polskiej 2017},
- author={Dominik Rozkrut i in},
+ author={Dominik Rozkrut},
journal={GUS},
volume={T. LXXVII},
pages={194--195},
- year={2016}
+ year={2017}
@Comment publisher={}
}
@misc{beautiful_soup,
- title = {BeautifulSoup},
- note = {Crummy.org},
+ title = {Strona internetowa {BeautifulSoup}},
key = {BeautifulSoup},
howpublished={\url{https://www.crummy.com/software/BeautifulSoup/}}
+ note = "Crummy.org [Online; dostęp 22.06.2018]"
}
-@misc{expotential_backoff}
-@misc{google_api}
-@misc{text_search}
-@misc{place_detail}
-@misc{jsonline}
-@misc{binaryornot}
-@misc{html2text}
-@misc{markdown}
-@misc{scrapy}
+@misc{expotential_backoff,
+ title = "Exponential backoff --- {Wikipedia}{,} The Free Encyclopedia",
+ year = "2018",
+ howpublished = "\url{https://en.wikipedia.org/w/index.php?title=Exponential_backoff&oldid=830252246}",
+ note = "[Online; dostęp 22.06.2018]"
+ }
+@misc{google_api,
+ title = "{Google Places API}",
+ howpublished = "\url{https://developers.google.com/places/web-service/intro}",
+ note = "[Online; dostęp 22.06.2018]"
+ }
+@misc{text_search,
+ title = "{Google Place Search}",
+ howpublished = "\url{https://developers.google.com/places/web-service/search}",
+ note = "[Online; dostęp 22.06.2018]"
+ }
+@misc{place_detail,
+ title = "{Google Place Details}",
+ howpublished = "\url{https://developers.google.com/places/web-service/details}",
+ note = "[Online; dostęp 22.06.2018]"
+ }
+@misc{jsonline,
+ title = "{Dokumentacja formatu JSON Lines}",
+ howpublished = "\url{jsonlines.org}",
+ note = "[Online; dostęp 22.06.2018]"
+ }
+@misc{html2text,
+ title = "{Repozytorium html2text}",
+ howpublished = "\url{https://github.com/Alir3z4/html2text}",
+ note = "[Online; dostęp 22.06.2018]"
+ }
+@techreport{markdown, author = {S. Leonard}, title = {The text/markdown Media Type}, howpublished = {Internet Requests for Comments}, type = {RFC}, number = {7763}, year = {2016}, month = {March}, issn = {2070-1721}, publisher = {RFC Editor}, institution = {RFC Editor}, }
+
+@misc{fingerprintjs2,
+ title = "{Dokumentacja fingerprintjs2}",
+ howpublished = "\url{https://github.com/Valve/fingerprintjs2/blob/master/README.md}",
+ note = "[Online; dostęp 22.06.2018]"
+ }
+@misc{softmax,
+ title = "Softmax function --- {Wikipedia}{,} The Free Encyclopedia",
+ year = "2018",
+ howpublished = "\url{https://en.wikipedia.org/w/index.php?title=Softmax_function&oldid=843761006}",
+ note = "[Online; dostęp 22.06.2018]"
+ }
+@article{scrapy,
+ author = {Myers, Daniel and McGuffee, James W.},
+ title = {Choosing Scrapy},
+ journal = {J. Comput. Sci. Coll.},
+ issue_date = {October 2015},
+ volume = {31},
+ number = {1},
+ month = oct,
+ year = {2015},
+ issn = {1937-4771},
+ pages = {83--89},
+ numpages = {7},
+ url = {http://dl.acm.org/citation.cfm?id=2831373.2831387},
+ acmid = {2831387},
+ publisher = {Consortium for Computing Sciences in Colleges},
+ address = {USA},
+}
+@article{word2vec,
+ author = {Xin Rong},
+ title = {word2vec Parameter Learning Explained},
+ journal = {CoRR},
+ volume = {abs/1411.2738},
+ year = {2014},
+ url = {http://arxiv.org/abs/1411.2738},
+ archivePrefix = {arXiv},
+ eprint = {1411.2738},
+ timestamp = {Wed, 07 Jun 2017 14:43:03 +0200},
+ biburl = {https://dblp.org/rec/bib/journals/corr/Rong14},
+ bibsource = {dblp computer science bibliography, https://dblp.org}
+}
+@misc{fasttext,
+Author = {Armand Joulin and Edouard Grave and Piotr Bojanowski and Tomas Mikolov},
+Title = {Bag of Tricks for Efficient Text Classification},
+Year = {2016},
+Eprint = {arXiv:1607.01759},
@article{parallel,
title = {GNU Parallel - The Command-Line Power Tool},
author = {O. Tange},
diff --git a/diagramy/struktura_programu.xml b/diagramy/struktura_programu.xml
index 0af012b..5a566d4 100644
--- a/diagramy/struktura_programu.xml
+++ b/diagramy/struktura_programu.xml
@@ -1 +1 @@
-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
\ No newline at end of file
+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
\ No newline at end of file
diff --git a/master.tex b/master.tex
index 38764cb..05970be 100644
--- a/master.tex
+++ b/master.tex
@@ -1,4 +1,4 @@
-\documentclass[a4paper, 12pt, twoside]{report}
+\documentclass[a4paper, 12pt, twoside, reqno]{report}
\input{pakiety.tex}
\input{ustawienia.tex}
@@ -51,14 +51,19 @@
\newpage\null\thispagestyle{empty}\newpage
% spis ilustracji:
-%\newpage
-%\listoffigures
-%\addcontentsline{toc}{chapter}{Spis ilustracji}
+\newpage
+\listoffigures
+\addcontentsline{toc}{chapter}{Spis rysunków}
+
+% spis algorytmów:
+\newpage
+\listofalgorithms
+\addcontentsline{toc}{chapter}{Spis algorytmów}
% spis tabel:
-%\newpage
-%\listoftables
-%\addcontentsline{toc}{chapter}{Spis tabel}
+\newpage
+\listoftables
+\addcontentsline{toc}{chapter}{Spis tabel}
%bibliografia
diff --git a/pakiety.tex b/pakiety.tex
index ddaed02..e849a16 100644
--- a/pakiety.tex
+++ b/pakiety.tex
@@ -5,6 +5,12 @@
\usepackage{makeidx} % indeks
\usepackage[pdftex]{graphicx} % zalaczanie grafiki
\usepackage{tikz} % grafika wektorowa
+\usepackage[
+ left = „,
+ right = ”,
+ leftsub = «,
+ rightsub = »
+]{dirtytalk} % cudzysłówy dla różnych języków \say{nic} --> "nic"
\usepackage{setspace} % interlinia
@@ -24,6 +30,7 @@
\usepackage{floatflt} % ladne oplywanie obrazkow tekstem
\usepackage{url} % url w bibliografii
\usepackage{amsmath}
+\usepackage{mathtools}
\usepackage{amsthm}
\usepackage[section]{placeins} %wymusza by obrazek był w obrębie sekacji a nie poza nią
diff --git a/rozdzial_3.tex b/rozdzial_3.tex
index b1e1d85..1a5a09e 100644
--- a/rozdzial_3.tex
+++ b/rozdzial_3.tex
@@ -1,13 +1,12 @@
-\chapter{Podstawy teoretyczne i/lub spis pojęć}
\chapter{Ekstrakcja godzin rozpoczęcia mszy świętych}
\section{Ogólny zarys systemu}
Architektura systemu ekstrakcji godzin rozpoczęcia mszy świętych została
-przedstawiona na rysunku \ref{pic:architektura}. W tym podrozdziale zostanie ona
+przedstawiona na rysunku \ref{pic:architektura}. W niniejszym podrozdziale zostanie ona
krótko opisana. Szczegółowy opis poszczególnych komponentów znajduje się w
-kolejnych podrozdziałach.
+podrozdziałach \ref{sub:zbieranie_informacji} - \ref{sub:klasyfikacja}.
System zaczyna działanie od zebrania jak największej ilości danych (nazwa parafii, adres, diecezja
-itd.) o polskich parafiach ze strony deon.pl. Następnie wysyła zapytania do interfejsu API
+itd.) o polskich parafiach ze strony \url{deon.pl}. Następnie wysyła zapytania do interfejsu API
Google w
celu znalezienia adresów internetowych parafii.
Dla każdej parafii, dla której udało się znaleźć adres URL, pobierane są wszystkie
@@ -16,7 +15,7 @@ podstrony w odległości\footnote{Zakładamy, że sieć jest grafem, zatem odleg
Z dużej liczby stron parafialnych, za pomocą reguł wyodrębnione zostają
te, na których z dużym prawdopodobieństwem znajdują się godziny mszy świętych.
-Następnie godziny zostają wydobyte ekstraktorem
+Następnie godziny zostają wydobyte ekstraktorem godzin
o bardzo niskiej precyzji i bardzo wysokiej wartości pokrycia.
Każda godzina wraz z kontekstem, w jakim się znajduje, trafia do anotatora.
Tam jest oznaczana jako poprawna lub niepoprawna godzina mszy
@@ -24,8 +23,8 @@ Tam jest oznaczana jako poprawna lub niepoprawna godzina mszy
godziny mszy świętych” rozumiemy godziny, które nie są
godzinami rozpoczęcia mszy świętych.}.
Regułowy ekstraktor mszy świętych o bardzo wysokiej precyzji znajduje poprawne
-godziny mszy świętych i dołącza je do zanotowanych danych.
-Dodatkowo w celu wyrównania
+godziny mszy świętych i dołącza je do zaanotowanych danych.
+Co więcej, w celu wyrównania
klas z nieodfiltrowanego zbioru stron parafialnych wylosowane zostają niepoprawne godziny mszy świętych.
Zebrane dane zostają użyte do wytrenowania klasyfikatora godzin opartego na
płytkich sieciach neuronowych.
@@ -53,6 +52,7 @@ znalezionych przez ekstraktor godzin do następujących klas:
\clearpage
\section{Zbieranie informacji o parafiach}
+\label{sub:zbieranie_informacji}
\begin{figure}[htb]
\center
@@ -61,10 +61,10 @@ znalezionych przez ekstraktor godzin do następujących klas:
\label{pic:pajak_nazw_parafii}
\end{figure}
Na rysunku \ref{pic:pajak_nazw_parafii} został przedstawiony fragment architektury
-systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
+systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Dane zostały zebrane z serwisu internetowego deon.pl, który zawiera 10130 parafii.
- Jest to większość polskich parafii, ponieważ według
+ Są to prawie wszystkie polskie parafie, ponieważ według
danych statystycznych GUS\cite{gus} z 2016 roku w Polsce było
10255 parafii.
@@ -91,14 +91,14 @@ Dla każdej parafii zebrano:
Św. Trójcy & Paszowice & Paszowic... & legnicka & Jawor & dolnośląskie\\
\\ [-1.5ex]
\end{tabular}
-\caption{Fragment zebranych danych.}
+\caption{Fragment danych zebranych przez pająka nazw i adresów parafii.}
\label{dane_tab}
\end{table}
Do wydobycia danych użyto skryptu w języku Python, który korzystał z parsera
HTML z biblioteki \textit{Beautiful Soup}\cite{beautiful_soup}. Przy wysyłaniu zapytań do serwisu deon.pl zastosowano
- algorytm \textit{Expotential Backoff}\cite{expotential_backoff}, który
- przedstawia się następująco:
+ algorytm \textit{Expotential Backoff}\cite{expotential_backoff}
+ (patrz algorytm \ref{alg:backoff}).
\begin{algorithm}
\setstretch{1.2}
@@ -138,7 +138,7 @@ Dla każdej parafii zebrano:
Algorytm \ref{alg:backoff} uodparnia skrypt na przejściowe problemy z połączeniem i
zapobiega zbyt częstemu wysyłaniu zapytań do serwisu. Dla przykładu załóżmy,
- że dany serwis jest obciążony i nie daje sobie rady z przetwarzaniem zapytań.
+ że dany serwis jest obciążony i odpowiada na zapytanie z dużym opóźnieniem.
Wtedy algorytm \textit{Expotential Backoff} przy każdym kolejnym niepowodzeniu
będzie czekał coraz dłużej, zanim wyśle kolejne zapytanie. W ten sposób nie
będzie niepotrzebnie obciążał serwisu.
@@ -153,14 +153,14 @@ Dla każdej parafii zebrano:
\end{figure}
Na rysunku \ref{pic:pajak_url} został przedstawiony fragment architektury
-systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
+systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
\subsubsection{Pierwsze próby}
Do wyszukiwania adresów URL parafii próbowano wykorzystać wyszukiwarki takie jak
Google i DuckDuckGo. Automatycznie wysyłano zapytanie złożone z konkatenacji
nazwy parafii, jej miejscowości i ulicy, na której się znajduje. Wyszukiwarka Google dawała
-zadowalające wyniki, jednak po kilkunastu zapytaniach blokowała adres IP. W
-dodatku w warunkach użytkowania serwisu i w pliku \textit{robots.txt} Google zabrania
+zadowalające wyniki, jednak po kilkunastu zapytaniach blokowała adres IP.
+Ponadto, w warunkach użytkowania serwisu i w pliku \textit{robots.txt} Google zabrania
korzystania z pająków na ich wyszukiwarce.
Wyszukiwarka DuckDuckGo nie blokowała adresu IP, ale zabraniała indeksowania w pliku \textit{robots.txt} i słabo radziła sobie z polskimi
zapytaniami. W obu przypadkach powyższa metoda stwarzała kolejny problem do
@@ -171,12 +171,12 @@ Po wielokrotnych próbach poszukiwań znaleziono klucz do rozwiązania problemu
wyszukiwania adresów URL, jakim jest
\textit{Google Places API}\cite{google_api}. Serwis \textit{Text Search}\cite{text_search} pozwala na wyszukanie miejsca
danego obiektu na
-podstawie jego nazwy. Ponadto mając już wyszukany dany obiekt i jego
+podstawie jego nazwy. Ponadto, mając już wyszukany dany obiekt i jego
identyfikator można odpytać serwis \textit{Place Detail}\cite{place_detail}, aby wyciągnąć więcej
szczegółów o danym miejscu. Między innymi można otrzymać adres URL danego obiektu.
Jedynym minusem jest ograniczenie liczby zapytań do 1000 na 24 godziny. W
-dodatku każde zapytanie do serwisu \textit{Text Search} traktowane jest jak 10
+dodatku, każde zapytanie do serwisu \textit{Text Search} traktowane jest jak 10
zapytań. Podając swoją kartę płatniczą, można zwiększyć limit
zapytań do 150 000 na 24 godziny. Karta płatnicza jest potrzebna Google do
identyfikacji osoby. Żadna opłata nie jest pobierana za korzystanie z interfejsu
@@ -193,10 +193,10 @@ przypadku brany jest adres URL pierwszego obiektu z listy wyników.
Najczęściej jednak oba obiekty należą do tej samej parafii, więc mają taki sam
adres internetowy. Taki przypadek przedstawia rysunek \ref{pic:text_search}.
Serwis \textit{Text Search} zwraca dużo danych w formacie JSON, które
-ciężko przedstawić w przejrzystej postaci.
+trudno jest przedstawić w przejrzystej postaci.
Dla
czytelności na rysunku \ref{pic:text_search} pokazano zrzuty ekranu z wyszukiwarki \textit{Google Maps},
-które odpowiadają rezultatowi, jaki otrzymano by, korzystając z serwisu
+które odpowiadają rezultatowi, jaki otrzymano, korzystając z serwisu
\textit{Text Search}.
\noindent Powyższą metodą udało się zebrać adresy URL dla ok. 5600 parafii.
@@ -222,7 +222,7 @@ które odpowiadają rezultatowi, jaki otrzymano by, korzystając z serwisu
Na rysunku \ref{pic:pajak_parafii_general} został przedstawiony fragment architektury
-systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
+systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Pająk został napisany przy użyciu biblioteki \textit{Scrapy}\cite{scrapy}.
Punktem startowym jest pojedynczy adres URL parafii podawany na wejście
@@ -235,17 +235,17 @@ asynchronicznie wysłać wiele zapytań do serwera i odbierać wiele odpowiedzi
Pająk składa się z następujących komponentów:
\begin{description}
\item [Silnik] -- odpowiada za kontrolę przepływu danych i komunikację między komponentami.
- \item [Dyspozytor] -- otrzymuje żądania od silnika, kolejkuje je i na
- prośbę silnika odsyła z powrotem.
+ \item [Dyspozytor] -- otrzymuje żądania od \textit{silnika}, kolejkuje je i na
+ prośbę \textit{silnika} odsyła z powrotem.
\item [Downloader] -- odpowiada za pobieranie stron parafialnych i
- przekazywanie ich silnikowi.
+ przekazywanie ich \textit{silnikowi}.
\item [Procesor danych] -- zajmuje się końcową obróbką i zapisem danych.
\item [Spider]\footnote{Użyto angielskiej nazwy, aby rozróżnić
\textit{spider'a} (komponent pająka), od pająka (cały program
odpowiedzialny za indeksowanie stron parafialnych).}
- definiuje sposób, w jaki pobierać dane, między innymi jak parsować stronę i za jakimi
linkami podążać.
- \item [Spider middleware] -- programy pośredniczące między silnikiem, a
+ \item [Spider middleware] -- programy pośredniczące między \textit{silnikiem}, a
\textit{spider'em}. Odpowiedzialne są za dodatkowe przetwarzanie danych wyjściowych
(dane parafialne i żądania) i wejściowych (odpowiedzi) \textit{spider'a}.
\item [Downloader middleware] -- programy pośredniczące między silnikiem, a
@@ -256,7 +256,7 @@ Pająk składa się z następujących komponentów:
\subsection{Przepływ danych}
Przepływ danych kontrolowany jest przez
-silnik i wygląda następująco\footnote{Diagram i opis wzorowany jest na
+\textit{silnik} i ma postać przedstawioną na rysunku \ref{pic:scrapy_data_flow}\footnote{Diagram i opis wzorowany jest na
dokumentacji znajdującej się pod linkiem https://doc.scrapy.org/en/latest/topics/architecture.html.}:
\begin{figure}[tbh]
@@ -265,34 +265,33 @@ silnik i wygląda następująco\footnote{Diagram i opis wzorowany jest na
\caption{Silnik kontrolujący przepływ danych przez komponenty pająka.}
\label{pic:scrapy_data_flow}
\end{figure}
-
\begin{enumerate}
- \item Silnik otrzymuje od \textit{spider'a} żądanie pobrania początkowej strony danej
+ \item \textit{Silnik} otrzymuje od \textit{spider'a} żądanie pobrania początkowej strony danej
parafii (najczęściej jest to strona główna parafii).
- \item Silnik oddaje żądania dyspozytorowi, który kolejkuje je do dalszego
- przetwarzania oraz pyta dyspozytora o żądania gotowe do przekazania \textit{downloader'owi}.
- \item Dyspozytor zwraca silnikowi następne żądania.
- \item Silnik wysyła żądania do \textit{downloader'a}. Zanim żądania dotrą do
+ \item \textit{Silnik} oddaje żądania \textit{dyspozytorowi}, który kolejkuje je do dalszego
+ przetwarzania oraz pyta \textit{dyspozytor} o żądania gotowe do przekazania \textit{downloader'owi}.
+ \item \textit{Dyspozytor} zwraca \textit{silnikowi} następne żądania.
+ \item \textit{Silnik} wysyła żądania do \textit{downloader'a}. Zanim żądania dotrą do
\textit{downloader'a}, przetwarzane są przez \textit{downloader middleware}.
\item \textit{Downloader} pobiera stronę parafialną i umieszcza ją w odpowiedzi, którą
- przesyła silnikowi. Zanim odpowiedź dotrze do silnika, przetwarzana jest przez
+ przesyła \textit{silnikowi}. Zanim odpowiedź dotrze do \textit{silnika}, przetwarzana jest przez
\textit{downloader middleware}.
- \item Silnik otrzymuje odpowiedź od \textit{downloader'a} i przekazuje ją \textit{spider'owi} do
+ \item \textit{Silnik} otrzymuje odpowiedź od \textit{downloader'a} i przekazuje ją \textit{spider'owi} do
dalszego przetwarzania. Zanim odpowiedź trafi, do \textit{spider'a} przetwarzana jest
przez \textit{spider middleware}.
- \item \textit{Spider} przerabia odpowiedź i zwraca dane strony parafialnej silnikowi. Zanim dane
- trafią, do silnika przechodzą przez \textit{spider middleware}. Dodatkowo \textit{spider}
+ \item \textit{Spider} przetwarza odpowiedź i zwraca dane strony parafialnej \textit{silnikowi}. Zanim dane
+ trafią do \textit{silnika}, przechodzą przez \textit{spider middleware}. Dodatkowo \textit{spider}
wysyła żądania z nowymi stronami parafialnymi do pobrania.
- \item Silnik wysyła zebrane dane do procesora danych, który zapisuje je do
+ \item \textit{Silnik} wysyła zebrane dane do \textit{procesora danych}, który zapisuje je do
pliku. Następnie przekazuje nowe żądania do zakolejkowania
- dyspozytorowi.
+ \textit{dyspozytorowi}.
\end{enumerate}
% \vspace*{-20mm}
Cały proces trwa dopóty, dopóki są nowe żądania do przetworzenia.
\subsection{Sprawdzanie typu odpowiedzi}
Podczas indeksowania ważne jest rozpoznawanie typu pobieranych danych. W przypadku
-indeksowania stron parafialnych interesują nas wyłącznie dane tekstowe. Należy
+indeksowania stron parafialnych przedmiotem zainteresowania są wyłącznie dane tekstowe. Należy
zatem zadbać o to, aby nie pobierać danych binarnych takich jak np. video, audio
i obrazy.
@@ -306,12 +305,14 @@ następujących kryteriach:
rozpoznać po nazwie pliku lub adresie URL).
\end{itemize}
Powyższy schemat postępowania jest skuteczny, jeśli serwisy internetowe zwracają
-poprawne odpowiedzi. Niestety niektóre strony parafialne potrafią zwracać
-odpowiedzi, które nie są zgodne z rozdziałem 3.1 z dokumentu RFC7231\cite{RFC7231}.
+poprawne odpowiedzi. Niestety, niektóre strony parafialne zwracają
+odpowiedzi, które nie są zgodne z rozdziałem 3.1 z dokumentu
+RFC7231\cite{RFC7231}\footnote{RFC to zbiór technicznych dokumentów w formie
+ memorandum opisujących protokoły związane z Internetem i sieciami komputerowymi.}.
Dla przykładu strona potrafi zwrócić \mintinline{bash}{Content-Type: text/html}
-w nagłówku, a w ciele binarną
+w nagłówku, a w ciele -- binarną
zawartość np. film. Tego rodzaju anomalie są wykrywane i eliminowane.
-\enlargethispage{2\baselineskip}
+\enlargethispage{3\baselineskip}
Stosując algorytm \ref{alg:binaryornot}, można określić typ zawartości
ciała odpowiedzi.
@@ -355,7 +356,7 @@ ciała odpowiedzi.
\end{algorithm}
Algorytm \ref{alg:binaryornot} analizuje zawartość ciała odpowiedzi w celu
-stwierdzenia czy jest ona binarna, czy nie.
+stwierdzenia, czy jest ona binarna, czy nie.
W linii 6 za znaki kontrolne uznano
wszystkie znaki kontrolne ze zbioru C0\footnote{C0 to znaki kontrolne z kodu
ASCII o kodach od 0 do 32 i o kodzie 127.} i C1\footnote{C1 to znaki kontrolne
@@ -377,7 +378,8 @@ Warto zwrócić uwagę na linię 10. Współczynnik
\mintinline{python}{control_char_ratio}
oznacza procent znaków kontrolnych w pierwszych 1024 bajtach pliku.
Jeśli współczynnik \mintinline{python}{control_char_ratio} jest większy niż
-$0,3$, to plik jest uznawany za binarny. Wartość $0,3$ została wzięta z
+$0,3$, to plik jest uznawany za binarny. Wartość $0,3$ została przyjęta z
+rozwiązania z
kodu\footnote{Kod znajduje się pod linkiem \url{https://github.com/Perl/perl5/blob/v5.27.11/pp\_sys.c\#L3605-L3665}. Wartość 0,3 występuje w linii 3661.}
źródłowego języka Perl, który między innymi zajmuje się rozpoznawaniem plików
binarnych. Natomiast współczynnik \mintinline{python}{high_ascii_ratio} oznacza
@@ -414,7 +416,7 @@ Załóżmy, że serwer potrzebuje
zdefiniowana w algorytmie \ref{alg:throttling}.} sekund, aby odpowiedzieć pająkowi. Jeśli pająk chce
mieć przetworzone równolegle
\mintinline{python}{target_concurrency}\footnote{Stała
- \mintinline{python}{target_concurrency} została zdefiniowana w algorytmie \ref{alg:throttling}.}zapytań to powinien
+ \mintinline{python}{target_concurrency} została zdefiniowana w algorytmie \ref{alg:throttling}.}zapytań, to powinien
wysyłać każde zapytanie co \mintinline{python}{latency/target_concurrency}
sekund.
@@ -511,7 +513,7 @@ indeksowania stron parafialnych.
\subsection{Organizacja danych}
\enlargethispage{1\baselineskip}
-Dane zbierane przez pająka zapisywane są do pliku w formacie JSONL. Format JSONL charakteryzuje się tym, że w każdej linii pliku
+Dane zbierane przez pająka zapisywane są do pliku w formacie JSONL\cite{jsonline}. Format JSONL charakteryzuje się tym, że w każdej linii pliku
znajduje się poprawny obiekt JSON.
Dla
każdej parafii pobrane dane zapisywane są w oddzielnym pliku. W każdej linii
@@ -520,7 +522,7 @@ Taki sposób organizacji danych przynosi szereg korzyści takich jak:
\begin{enumerate}
\item wygodne przetwarzanie równoległe,
\item łatwa obróbka danych za pomocą narzędzi Uniksowych,
-\item mniejszy rozmiar pliku w porównaniu do zwykłego formatu \textit{JSON}.
+\item mniejszy rozmiar pliku w porównaniu do zwykłego formatu JSON.
\end{enumerate}
\noindent Dla każdej strony parafialnej zapisywane są następujące informacje:
@@ -543,7 +545,7 @@ Taki sposób organizacji danych przynosi szereg korzyści takich jak:
\end{figure}
Na rysunku \ref{pic:html2text} został przedstawiony fragment architektury
-systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
+systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Do konwersji z formatu HTML na format tekstowy wykorzystano bibliotekę \mintinline{bash}{html2text}\cite{html2text}
pierwotnie rozwijaną przez Aarona Schwartza.
@@ -570,7 +572,7 @@ konwersji i jest bardzo łatwa w modyfikacji.
\label{pic:general_ekstraktor}
\end{figure}
Na rysunku \ref{pic:html2text} został przedstawiony fragment architektury
-systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
+systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Ekstraktor godzin służy do znajdowania bardzo ogólnych ciągów znaków mogących
być godzinami rozpoczęcia mszy świętych. Został napisany z myślą, aby miał
@@ -603,7 +605,7 @@ Ekstraktor wraz
\label{pic:filtrowanie}
\end{figure}
Na rysunku \ref{pic:filtrowanie} został przedstawiony fragment architektury
-systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
+systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
Filtr stron parafialnych ma za zadanie odnaleźć strony parafialne, na których z
dużym prawdopodobieństwem znajdują się godziny mszy świętych. Taki zabieg jest
@@ -687,6 +689,7 @@ W algorytmie \ref{alg:has_mass} warto zwrócić uwagę na wyrażenia regularne
się tam wyrażenia takie jak „nabożeństwa czerwcowe” czy „nabożeństwa maryjne”.
\section{Anotator danych}
+\label{sec:anotator}
\begin{figure}[tbh!]
@@ -698,13 +701,21 @@ W algorytmie \ref{alg:has_mass} warto zwrócić uwagę na wyrażenia regularne
\end{figure}
Na rysunku \ref{pic:anotator} został przedstawiony fragment architektury
-systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w tym podrozdziale.
+systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
\subsection{Ogólny zarys}
+\label{subsec:anotator}
+\begin{figure}[tbh!]
+\center
+\includegraphics[width=0.4\hsize]{antoator.jpg}
+\caption{Zrzut ekranu pokazujący interfejs anotatora na urządzeniu mobilnym.}
+\label{pic:antoator}
+\end{figure}
+
Anotator danych został stworzony w celu zebrania jak największej ilości
danych dla klasyfikatora przewidującego czy zaznaczony fragment jest godziną
rozpoczęcia mszy świętej, czy nie.
-Aby osiągnąć zamierzony cel anotator został zaprojektowany w ten sposób aby:
+Żeby osiągnąć zamierzony cel, anotator został zaprojektowany w ten sposób, aby:
\begin{itemize}
\item był szybki,
\item był dostępny na urządzeniach mobilnych i stacjonarnych,
@@ -712,60 +723,467 @@ Aby osiągnąć zamierzony cel anotator został zaprojektowany w ten sposób aby
\item umożliwiał wykrywanie oszustów (osób intencjonalnie źle anotujących).
\end{itemize}
+
\noindent Anotator jest dostępny jako aplikacja internetowa pod adresem \url{msze.nsupdate.info}. Aplikacja jest
responsywna, więc można z niej wygodnie korzystać na każdym urządzeniu
-wyposażonym w co najmniej 4 calowy wyświetlacz. Interfejs jest przejrzysty i
-został pokazany na rysunku X. Jedyne akcje jakie może wykonać użytkownik to:
+wyposażonym w co najmniej 4-calowy wyświetlacz. Interfejs jest przejrzysty i
+został pokazany na rysunku \ref{pic:antoator}. Jedyne akcje, jakie może wykonać użytkownik to:
\begin{itemize}
-\item kliknąć „Tak” jeśli zaznaczono godzinę rozpoczęcia mszy,
-\item kliknąć „Nie” jeśli zaznaczono inną godzinę,
+\item kliknąć „Tak”, jeśli zaznaczono godzinę rozpoczęcia mszy,
+\item kliknąć „Nie”, jeśli zaznaczono inną godzinę,
\item cofnąć się do poprzedniej anotacji,
\item wyświetlić instrukcję obsługi.
\end{itemize}
Po naciśnięciu przycisku „Tak” lub „Nie” ekran jest automatycznie przewijany na
sam dół. Taka operacja zapewnia łatwy dostęp do przycisków odpowiedzialnych za anotację. Dzięki
-temu znajdują się one również zawsze w tym samym miejscu co ułatwia szybką
+temu znajdują się one również zawsze w tym samym miejscu, co ułatwia szybką
anotację.
Po naciśnięciu przycisku „Cofnij” ekran nie jest już przewijany na sam dół. W
ten sposób zapewniono wygodny dostęp do przycisku „Cofnij”. Jest to szczególnie
istotne w przypadku gdy
użytkownik zamierza cofać się wiele razy.
-Aby zapewnić odpowiednią jakość anotacji przy pierwszym urchomieniu wyświetlana
-jest instrukcja obsługi. Opisuje ona sposób w jaki należy anotować godziny oraz
-przedstawia przykłady poprawnie zanotowanych godzin. Intrukcję można zamknąć
+Aby zapewnić odpowiednią jakość anotacji, przy pierwszym uruchomieniu wyświetlana
+jest instrukcja obsługi. Opisuje ona sposób, w jaki należy anotować godziny oraz
+przedstawia przykłady poprawnie zaanotowanych godzin. Instrukcję można zamknąć
dopiero po przewinięciu jej na sam dół.
Aplikacja nie wymaga logowania. Taka
decyzja została podjęta ze względu na fakt, że anotatorami są wolontariusze.
Wymóg rejestracji i logowania spowodowałby zmniejszenie liczby osób chętnych do
anotacji. Takie podejście wiąże się jednak z problemem identyfikacji
-użytkowników. Identyfikacja jest niezbędna do prawidłowego funkcjonawania
-antotora. Chcielibyśmy wiedzieć, które godziny zostały zanotowane przez danego
+użytkowników. Identyfikacja jest niezbędna do prawidłowego funkcjonowania
+antotora. Chcielibyśmy wiedzieć, które godziny zostały zaanotowane przez danego
użytkownika, aby między innymi nie dać mu tych samych godzin do anotacji.
\subsection{Identyfikacja urządzeń}
-Skuteczną identyfikację można przeprowadzić używając
+\enlargethispage{3\baselineskip}
+Skuteczną identyfikację można przeprowadzić, używając ciasteczek oraz pobierając różne informacje o urządzeniu.
+Za pomocą biblioteki \mintinline{text}{fingerprintjs2} można między innymi zebrać następujące
+dane o kliencie\cite{fingerprintjs2}:
+\begin{enumerate}
+\item wersję przeglądarki,
+\item język,
+\item głębię koloru,
+\item rozdzielczość ekranu,
+\item strefę czasową,
+\item obsługę \textit{localStorage}\footnote{Obiekt przechowujący dane w
+ przeglądarce bez daty ważności.},
+\item obsługę \textit{sessionStorage}\footnote{Obiekt przechowujący dane w
+ przeglądarce tylko na czas sesji (po zamknięciu przeglądarki dane są usuwane).},
+\item wspieranie \textit{indexed DB}\footnote{Niskopoziomy interfejs API dla
+ transakcyjnej bazy danych do przechowywania ustrukturyzowanych danych.},
+\item klasę CPU,
+\item system operacyjny,
+\item listę zainstalowanych czcionek,
+\item listę zainstalowanych wtyczek,
+\item \textit{Canvas fingerprint}\footnote{Mechanizm do tworzenia odcisków palca
+ przeglądarki na podstawie HTML5 Canvas. HTML5 Canvas to element języka HTML
+ służący do renderowania obrazów bitmapowych.},
+\item \textit{WebGL fingerprint}\footnote{Mechanizm do tworzenia odcisków palca
+ przeglądarki na podstawie obrazków generowanych przez silnik do rysowania
+ grafiki \textit{WebGL}.},
+\item \textit{Audio fingerprint}\footnote{Mechanizm do tworzenia odcisków palca
+ przeglądarki za pomocą analizy sygnału audio.},
+\item \textit{Pixel ratio}\footnote{Jest to stosunek rozdzielczości logicznej do
+ rozdzielczości fizycznej.},
+\item liczbę procesorów logicznych,
+\item pojemność pamięci RAM.
+\end{enumerate}
+
+\noindent Nadawanie identyfikatora nowemu urządzeniu, a potem jego identyfikacja przedstawia się następująco:
+\begin{enumerate}
+ \item Klient wysyła żądanie GET w celu załadowania anotatora.
+ \item Anotator ładuje się w przeglądarce i oblicza \textit{odcisk
+ palca}\footnote{Odcisk palca przeglądarki
+ to informacje zebrane w celu jej identyfikacji.}
+ przeglądarki za pomocą biblioteki \textit{fingerprintjs2}. Obliczony \textit{odcisk
+ palca} będzie dołączany do każdego kolejnego żądania.
+ \item Klient wysyła serwerowi nowe żądanie z prośbą wyświetlenia fragmentu z
+ godziną do anotacji. Wraz z żądaniem przesyłany jest \textit{odcisk palca} przeglądarki.
+ \item Serwer odbiera żądanie od klienta i oblicza unikalny identyfikator dla
+ klienta. Serwer zapisuje w bazie danych, że \textit{odciskowi palca} wysłanemu przez
+ klienta odpowiada wygenerowany identyfikator.
+ \item Serwer wysyła klientowi fragment do anotacji wraz z wcześniej
+ wygenerowanym identyfikatorem, który zostaje zapisany w nagłówku \textit{Set-Cookie}.
+ \item Klient odbiera fragment do anotacji. Zostaje on wyświetlony na ekranie
+ urządzenia. Identyfikator zawarty w nagłówku \textit{Set-Cookie} zostaje
+ zapisany w przeglądarce klienta. W tym momencie kończy się ładowanie anotatora.
+ \item Przy każdym kolejnym żądaniu ciasteczko z
+ identyfikatorem jest wysyłane do serwera. Na jego podstawie serwer
+ identyfikuje dane urządzenie. Jeśli użytkownik usunie ciasteczka z
+ urządzenia i wyśle kolejne zapytanie, to serwer zidentyfikuje użytkownika po
+ \textit{odcisku palca} przeglądarki i w nagłówku \textit{Set-Cookie} prześle
+ pierwotny identyfikator przydzielony danemu urządzeniu.
+\end{enumerate}
+\enlargethispage{3\baselineskip}
\subsection{Architektura anotatora}
-Architektura
-\subsection{Podsumowanie}
+Architektura anotatora została przedstawiona na rysunku \ref{pic:anotator_detailed}.
+Komunikacja między serwerem a klientem przedstawia się następująco:
+\begin{enumerate}
+ \item Klient wysyła żądanie do serwera.
+ \item Serwer \textit{nginx} odbiera żądanie od klienta i przekazuje je serwerowi
+ \textit{Gunicorn}.
+ \item Serwer \textit{Gunicorn} przekazuje żądanie wolnemu wątkowi roboczemu.
+ Jeśli każdy wątek roboczy jest zajęty, żądanie zostanie przekazane
+ pierwszemu wolnemu wątkowi roboczemu.
+ \item Aplikacja webowa \textit{Flask} przetwarza żądanie. W zależności od żądania odpowiednio
+ modyfikuje dane w bazie \textit{Redis}.
+ \item Aplikacja webowa \textit{Flask} zwraca kolejną godzinę do
+ anotacji z \textit{listy fragmentów do anotacji} i przekazuje ją w postaci
+ odpowiedzi do serwera \textit{Gunicorn}.
+ \item Serwer \textit{Gunicorn} odbiera odpowiedź i przekazuje ją serwerowi \textit{nginx}.
+ \item Serwer \textit{nginx} wysyła odpowiedź klientowi.
+\end{enumerate}
+
+\clearpage
+\begin{figure}[t]
+\centering
+\includegraphics[width=0.65\hsize]{annotator_detailed.png}
+\caption{Architektura anotatora.}
+\label{pic:anotator_detailed}
+\end{figure}
+
\section{Regułowa ekstrakcja godzin mszy}
-Do napisania
-\section{Klasyfikacja godzin}
-Do napisania
-\subsection{Model teoretyczny}
-\subsection{FastText}
+\begin{figure}[tbh!]
+\center
+\includegraphics[width=0.6\hsize]{ekstraktor_regulowy.png}
+\caption{Fragment architektury systemu przedstawiający komponent odpowiedzialny
+ za ekstrakcję godzin rozpoczęcia mszy świętych.}
+\label{pic:ekstraktor_regulowy}
+\end{figure}
+Na rysunku \ref{pic:ekstraktor_regulowy} został przedstawiony fragment architektury
+systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
+Ekstraktor regułowy oparty jest na wyrażeniach regularnych.
+Wyróżniamy pięć kluczowych fragmentów wyszukiwanych przez ekstraktor godzin. Są
+to:
+\begin{description}[labelindent=15pt, style=multiline, leftmargin=5.5cm]
+ \item [główny nagłówek] -- nagłówek rozpoczynający spis godzin mszy świętych (np. \say{porządek mszy}) lub \say{msze
+ święte}. Jest on ekstrahowany przez wyrażenie regularne\footnote{Zakładamy
+ , że wyrażenia regularne ignorują wielkość liter.}\\
+ \mintinline[breaklines]{text}{'porządek mszy (świętych|św|św\.)|}\\
+ \mintinline[breaklines]{text}{msz[ea][\n]+([śs]wi[eę]t[ea]|św|św\.)'}
+ \item [nagłówek niedzielny] -- nagłówek, po którym występują niedzielne i świąteczne
+ godziny mszy (np. \say{porządek świąteczny}). Jest on ekstrahowany przez
+ wyrażenie regularne\\
+ \mintinline[breaklines]{text}{'niedziel[a|e][ \n]+i[ \n]+(dni[ \n]+}\\
+ \mintinline[breaklines]{text}{(świąteczne|św|św\.)|święta)|niedziel[ea]|}\\
+ \mintinline[breaklines]{text}{porządek świąteczny'}
+ \item [niedzielne godziny] -- niedzielne i świąteczne godziny mszy świętych.
+ Są one ekstrahowane przez wyrażenie regularne \\\mintinline[breaklines]{text}{'.*[^\d]\d{1,2}[^\d].*?''}
+ \item [nagłówek powszedni] -- nagłówek, po którym występują godziny mszy
+ świętych dla dni powszednich (np. \say{w tygodniu}). Jest on ekstrahowany
+ przez wyrażenie regularne \\\mintinline[breaklines]{text}{'dzień powszedni|dni powszednie|w tygodniu| porządek zwykły|od poniedziałku do soboty'}
+ \item [powszednie godziny] -- powszednie godziny mszy świętych. Są one
+ ekstrahowane przez wyrażenie regularne \\\mintinline[breaklines]{text}{'(.*?[^\d\n]?\d{1,2}[^\d\n]?.*?\n)+'}.
+
+\end{description}
+W dużym uproszczeniu ekstrakcja godzin przedstawia się następująco:
+\begin{enumerate}
+ \item Wyszukaj \textit{nagłówek główny}, \textit{nagłówek niedzielny} i
+ \textit{nagłówek powszedni} w taki sposób, aby:
+ \begin{itemize}
+ \item \textit{nagłówek niedzielny} był za \textit{nagłówkiem głównym}, ale
+ przed \textit{nagłówkiem powszednim}.
+ \item między \textit{nagłówkiem głównym} a \textit{nagłówkiem powszednim}
+ nie znajdował się żaden inny \textit{nagłówek} niż
+ \textit{nagłówek niedzielny}
+ \end{itemize}
+ \item Jeśli wyszukiwanie w kroku 2. się nie powiodło, szukaj na kolejnej stronie parafialnej.
+ \item Niedzielnymi i świątecznymi godzinami mszy świętych będą godziny między
+ \textit{nagłówkiem niedzielnym} a \textit{nagłówkiem powszednim} pasujące
+ do wyrażenia regularnego \textit{niedzielnych godzin}. Jeśli wyszukiwanie
+ się nie powiedzie, to rozpocznij szukanie od początku na kolejnej stronie parafialnej.
+ \item Godzinami powszednimi, będą godziny po \textit{nagłówku powszednim}
+ pasujące do wyrażenia regularnego \textit{powszednich godzin}. Jeśli wyszukiwanie
+ się nie powiedzie, to rozpocznij szukanie od początku na kolejnej stronie parafialnej.
+
+\end{enumerate}
+
+\section{Klasyfikacja godzin}
+\label{sub:klasyfikacja}
+
+\begin{figure}[tbh!]
+\center
+\includegraphics[width=0.9\hsize]{klasyfikator.png}
+\caption{Fragment architektury systemu przedstawiający komponent odpowiedzialny
+ za klasyfikację godzin.}
+\label{pic:klasyfikator}
+\end{figure}
+Na rysunku \ref{pic:klasyfikator} został przedstawiony fragment architektury
+systemu z rysunku \ref{pic:architektura}, który zostanie omówiony w niniejszym podrozdziale.
+
+
+Klasyfikator opary jest na płytkich sieciach neuronowych optymalizowanych metodą
+stochastycznego spadku wzdłuż gradientu z
+liniowo malejącym współczynnikiem uczenia. Został on wykorzystany do klasyfikacji
+godzin na te będące godzinami mszy świętych i na te nimi niebędące.
+
+\subsection{Model teoretyczny}
+\label{subsec:model_teoretyczny}
+
+Podrozdział opiera się na artykule \textit{word2vec Parameter Learning
+ Explained}\cite{word2vec} i artykule \textit{Bag of Tricks for Efficient Text Classification}\cite{fasttext}.
+\subsubsection{Notacja}
+W podrozdziale \ref{subsec:model_teoretyczny} przyjęto poniższą notację.
+\boldmath %\unboldmath
+\begin{description}[labelindent=25pt, style=multiline, leftmargin=2.5cm]
+
+\item[$X_{V\times N}$] -- macierz $X$ o $V$ wierszach i $N$ kolumnach.
+\item [$X_{i,j}$] -- wartość w macierzy $X$ w wierszu $i$ i kolumnie $j$.
+\item [$X_{i,*}$] -- wiersz $i$ w macierzy $X$.
+\item [$X_{*,j}$] -- kolumna $j$ w macierzy $X$.
+\item [$x_i$] -- $x_i$ wartość pod indeksem $i$ w wektorze $x$.
+ \item [$w_i$] -- wektor słowa o indeksie $i$.
+ \item [$w_{i,j}$] -- wartość pod indeksem $j$ w $i$-tym słowie.
+\end{description}
+
+\subsubsection{Architektura sieci}
+
+\begin{figure}[tbh!]
+\center
+\includegraphics[width=0.6\hsize]{cbow.png}
+\caption{Architektura sieci neuronowej.}
+\label{pic:cbow}
+\end{figure}
+
+Rysunek \ref{pic:cbow}\footnote{Rysunek wzorowany jest na rysunku z artykułu \textit{word2vec Parameter Learning
+ Explained}\cite{word2vec}} przedstawia sieć neuronową, która służy do klasyfikacji
+tekstu.
+Wejście do sieci składa się z wektorów słów $w_1, \dots, w_C$, gdzie $w_1,
+\dots, w_C$ to słowa z klasyfikowanego zdania. Wektory słów zakodowane
+zostały za pomocą kodowania \textit{one-hot encoding}\footnote{Sposób kodowania
+ zwany jako \say{kod 1 z n}.}.
+ Na wejściu mamy $C$ wektorów słów o rozmiarze $V$, gdzie $V$ to rozmiar
+ słownika, a $C$ to liczba słów w zdaniu. Każdy wektor słów połączony jest z warstwą
+ ukrytą $h$ macierzą wag $W_{V\times N}$ (współdzielą tę samą macierz). Warstwa
+ ukryta $h$ jest rozmiaru $N$. Warstwa ukryta $h$ łączy się z warstwą wyjściową
+ macierzy $H_{N\times K}$. Warstwa wyjściowa $y$ jest rozmiaru $K$, gdzie $K$
+ to liczba klas.
+ Sieć klasyfikuje zdania do klas $k_1, \dots, k_K$.
+
+ \subsubsection{Propagacja w przód}
+
+ Warstwa ukryta jest wynikiem średniej z wektorów słów $w_1, \dots,
+ w_C$\footnote{Zakładamy, że wektory są wektorami wierszowymi.}
+ pomnożonych przez macierz $W_{V\times N}$ (patrz równanie \ref{eq:hidden}).
+
+\begin{equation}
+ \label{eq:hidden}
+ h=\frac{1}{c} \sum_{i=1}^{C}{w_i W}=\frac{1}{c} (\sum_{i}^{C}{w_i }) \cdot W
+\end{equation}
+
+W warstwie wyjściowej jako funkcja aktywacji została zastosowana funkcja
+\textit{softmax}\cite{softmax}. Wejście o indeksie $j$ do funkcji \textit{softmax} obliczane jest za pomocą równania \ref{eq:softmax_input}.
+\begin{equation}
+ \label{eq:softmax_input}
+ u_j=h\cdot H_{*,j}
+\end{equation}
+
+$y_j$ w warstwie wyjściowej otrzymujemy używając funkcji \textit{softmax} zgodnie z równaniem \ref{eq:output_y}
+\begin{equation}
+ \label{eq:output_y}
+y_j = \frac{exp(u_j)}{\sum_{i=1}^{K}{exp(u_i)}}
+\end{equation}
+Funkcja \textit{softmax} normalizuje nam wektor wyjściowy. Dzięki niej na
+wyjściu z sieci otrzymujemy rozkład prawdopobieństwa klas. Możemy zatem zapisać, że
+\begin{equation}
+ \label{eq:probyj}
+p(k_j|w_1,w_2, \dots, w_C) = y_j,
+\end{equation}
+gdzie $k_j$ to klasa o indeksie $j$.
+
+\subsubsection{Proces uczenia sieci neuronowej}
+Proces uczenia zaczynamy od zainicjalizowania macierzy $W_{V\times N}$ i
+$H_{N\times K}$ losowymi wartościami. Następnie przeprowadzamy propagację w
+przód i obliczamy błąd między aktualnym a oczekiwanym wyjściem. Następnie
+obliczamy gradient funkcji kosztu i poprawiamy wartości macierzy $W$ i $H$ w
+kierunku gradientu.
+
+Celem jest maksymalizacja prawdopobieństwa $p(k_{j^*}|w_1, \dots w_C)$ (patrz równania \ref{eq:max_start} - \ref{eq:max_end}), gdzie $k_{j^*}$
+to wyjściowa klasa o indeksie $j^*$.
+\begin{align}
+ \label{eq:max_start}
+ max(p(k_{j^*}|w_1, \dots w_C)) &= max(\frac{exp(u_{j^*})}{\sum_{i=1}^{K}{exp(u_i)}}) &\text{z \ref{eq:probyj} i \ref{eq:output_y}}\\
+ &= max(log(\frac{exp(u_{j^*})}{\sum_{i=1}^{K}{exp(u_i)}}))\\
+ \label{eq:max_end}
+ &= max(u_{j^*} - log(\sum_{i=1}^{K}{exp(u_i)}))
+\end{align}
+Zatem funkcja kosztu (celem jest jej minimalizacja) będzie przedstawiała się tak
+jak na równaniu \ref{eq:loss}.
+
+\begin{align}
+ E&=-(u_{j^*} - log(\sum_{i=1}^{K}{exp(u_i)})) &\text{z \ref{eq:max_end}}\\
+ \label{eq:loss}
+&=log(\sum_{i=1}^{K}{exp(u_i)}) -u_{j^*}
+\end{align}
+
+\subsubsection{Aktualizowanie wag macierzy $H_{N\times K}$}
+Najpierw należy policzyć pochodną cząstkową funkcji kosztu $E$ względem wektora
+$u$ (patrz równania \ref{eq:deu_start} - \ref{eq:deu_end}).
+\begin{align}
+ \label{eq:deu_start}
+ \frac{\partial E}{\partial u_j} &= \frac{\partial(log(\sum_{i=1}^{K}{exp(u_i)}) -u_{j^*})}{\partial u_j}\\
+&=\frac{\partial(log(\sum_{i=1}^{K}{exp(u_i)}))}{\partial u_j} - \frac{\partial u_{j^*}}{\partial u_{j}}\\
+ \shortintertext{Z reguły łańcuchowej otrzymujemy:}
+ &=\frac{\partial(\sum_{i=1}^{K}{exp(u_i)})}{\partial u_{j}} \cdot \frac{\partial(log(\sum_{i=1}^{K}{exp(u_i)}))}{\partial(\sum_{i=1}^{K}{exp(u_i)})} - \frac{\partial u_{j^*}}{\partial u_{j}}\\
+ &= exp(u_j) \cdot \frac{1}{\sum_{i=1}^{K}{exp(u_i)}} - \frac{\partial u_{j^*}}{\partial u_{j}}\\
+ &= y_j - \frac{\partial u_{j^*}}{\partial u_{j}} &\text{z \ref{eq:output_y}}\\ \shortintertext{Za $\frac{\partial u_{j^*}}{\partial u_{j}}$ podstawiamy $t_j$:}
+\label{eq:deu_end}
+ &= y_j - t_j \vcentcolon= e_j\\\shortintertext{gdzie $t_j = 1$, gdy $j = j^*$, w przeciwnym wypadku $t_j = 0$.}\nonumber
+\end{align}
+
+Pochodna $e_j$ to błąd predykcji warstwy wyjściowej.
+Gradient dla wag z macierzy $H$ otrzymamy, licząc pochodną cząstkową
+funkcji kosztu $E$ względem wag macierzy $H$ (patrz równania \ref{eq:der_start} - \ref{eq:der_end}).
+\begin{align}
+ \label{eq:der_start}
+ \frac{\partial E}{\partial H_{i,j}}&=\frac{\partial E}{\partial u_j} \cdot \frac{\partial u_j}{\partial H_{i,j}} &\text{z reguły łańcuchowej}\\
+ &= e_j \cdot \frac{\partial(h \cdot H_{*,j})}{\partial H_{i,j}} &\text{z \ref{eq:softmax_input}}\\
+ &= e_j \cdot \frac{\partial(\sum_{i'=1}^{N}{h_{i'} \cdot H_{i',j}})}{\partial H_{i,j}} &\text{z definicji mnożenia macierzy}\\
+ \label{eq:der_end}
+ &= e_j \cdot h_i
+\end{align}
+
+\noindent Aktualizowanie wag macierzy $H$ zostało przedstawione w równaniu \ref{eq:update_h}.
+\begin{align}
+\label{eq:update_h}
+ H_{i,j}^{nowe} = H_{i,j}^{stare} - \eta \cdot e_j \cdot h_i\\ \shortintertext{gdzie $\eta$ to liniowo malejący współczynnik uczenia.}\nonumber
+\end{align}
+\subsubsection{Aktualizowanie wag macierzy $W_{V\times N}$}
+Najpierw należy policzyć pochodną cząstkową funkcji kosztu $E$ względem warstwy
+ukrytej $h$ (patrz równania \ref{eq:sumder_start} - \ref{eq:sumder_end}).
+\begin{align}
+ \label{eq:sumder_start}
+ \frac{\partial E}{\partial h_i} &= \sum_{j=1}^{K}{\frac{\partial E}{\partial u_j} \cdot \frac{\partial u_j}{\partial h_i}} &\text{z reguły łańcuchowej}\\
+ &= \sum_{j=1}^{K}{e_j \cdot \frac{\partial(h \cdot H_{*,j})}{\partial h_i}} &\text{z \ref{eq:softmax_input} i z \ref{eq:deu_start} - \ref{eq:deu_end}}\\
+ &= \sum_{j=1}^{K}{e_j \cdot \frac{\partial(\sum_{i'=1}^{N}{h_i' \cdot H_{i',j}})}{\partial h_i}} &\text{z definicji mnożenia macierzy}\\
+ \label{eq:sumder_end}
+&= \sum_{j=1}^{K}{e_j \cdot H_{i,j}}
+\end{align}
+W równaniu \ref{eq:sumder_start} mamy do czynienia z sumą ze względu na fakt,
+że neuron $h_i$ połączony jest z $K$ neuronami warstwy wyjściowej. Każdy błąd
+predykcji powinien być uwzględniony.
+
+Następnie należy policzyć pochodną cząstkową funkcji $E$ względem wag w macierzy
+$W$ (patrz \ref{eq:last_der_start} - \ref{eq:last_der_end}).
+\begin{align}
+ \label{eq:last_der_start}
+ \shortintertext{Z reguły łańcuchowej:}
+\frac{\partial E}{\partial W_{k,i}} &= \frac{\partial E}{\partial h_i} \cdot \frac{\partial h_i}{\partial W_{k,i}}&\text{}\\
+ \shortintertext{Z \ref{eq:sumder_start} - \ref{eq:sumder_end} i z \ref{eq:hidden}:}
+ &= (\sum_{j=1}^{K}{e_j \cdot H_{i,j}}) \cdot \frac{\partial (\frac{1}{C}(\sum_{i'=1}^{C}{w_{i'}})W_{*,i})}{\partial W_{k,i}}\\
+ \shortintertext{Z definicji mnożenia macierzy:}
+ &=(\sum_{j=1}^{K}{e_j \cdot H_{i,j}}) \cdot \frac{\partial (\frac{1}{C}\sum_{l=1}^{V}((\sum_{i'=1}^{C}{w_{i',l}})W_{l,i}))}{\partial W_{k,i}}\\
+ &=(\sum_{j=1}^{K}{e_j \cdot H_{i,j}}) \cdot \frac{1}{C}\sum_{i'=1}^{C}{w_{i',k}}\\
+ \intertext{Zauważmy, że $\sum_{i'=1}^{C}{w_{i',k}}=1$, bo wektory słów zakodowane są kodowaniem \textit{one-hot encoding}. Innymi słowy jest tylko jeden wektor słowa, który ma wartość 1 pod indeksem $k$. Reszta wektorów słów ma pod indeksem $k$ wartość 0. Zatem otrzymujemy:}
+ &=\frac{1}{C}\sum_{j=1}^{K}{e_j \cdot H_{i,j}}
+ \label{eq:last_der_end}
+\end{align}
+
+\noindent Aktualizowanie wag macierzy $W$ zostało przedstawione w równaniu \ref{eq:final}.
+\begin{equation}
+ \label{eq:final}
+W_{i,j}^{nowe} = W_{i,j}^{stare} - \eta \frac{1}{C} \sum_{j=1}^{K}{e_j \cdot H_{i,j}}
+\end{equation}
+
+\subsection{FastText}
+Autorzy biblioteki \textit{fastText} wskazują, że podstawowy model opisany w
+podrozdziale \ref{subsec:model_teoretyczny} można usprawnić. Do modelu można
+dodać dodatkowe cechy w postaci \textit{n-gramów}(w modelu z podrozdziału
+\ref{subsec:model_teoretyczny} zostały zastosowane unigramy). Artykuł
+\textit{Bag of Tricks for Efficient Text Classification}\cite{fasttext} pokazuje,
+że dodanie bigramów poprawia wyniki klasyfikatora.
+Ponadto, aby przyspieszyć trenowanie, można zastosować funkcję \textit{hierarchical
+ softmax}\cite{fasttext}, zamiast funkcji \textit{softmax}. Taka operacja jest korzystna w
+przypadku dużej liczby klas \cite{fasttext}. W przypadku klasyfikacji godzin użyto funkcji
+\textit{softmax} ze względu na małą liczbę klas.
+Do klasyfikacji użyto biblioteki \textit{fastText} z domyślnymi parametrami.
+Rezultaty zostały przedstawione w rozdziale \ref{ch:rezultaty}.
\chapter{Rezultaty}
-Do napisania
-% \section{Organizacja danych} % może zbyt inżynierskieby
+\label{ch:rezultaty}
+W niniejszym rozdziale zebrane zostały wyniki, jakie osiągnął system ekstrakcji
+informacji o godzinach rozpoczęcia mszy świętych.
+\subsubsection{Dane parafii i ich adresy URL}
+\noindent Udało się zebrać:
+\begin{itemize}
+ \item \textbf{10130} nazw i adresów parafii,
+ \item \textbf{5600} adresów internetowych stron parafialnych,
+\end{itemize}
+Ręcznie na małej próbce adresów
+URL stwierdzono, że
+w ponad 90\% prowadzą one do poprawnych parafii.
+
+Warto zaznaczyć, że w momencie oddania pracy do druku nie znaleziono
+obszerniejszego zbioru adresów URL parafii. Serwisy internetowe zawierające
+adresy URL parafii posiadały nie więcej niż 2500 tysiąca adresów URL parafii.
+Większość z nich to były błędne adresy internetowe.
+
+\subsubsection{Pająk}
+Z \textbf{5600} adresów internetowych parafii pająk zaindeksował \textbf{5177} stron parafialnych.
+W kilka dni pobrał około \textbf{3 000 000} stron HTML o łącznym rozmiarze \textbf{152G}. Po
+konwersji stron parafialnych z formatu HTML do formatu tekstowego otrzymano \textbf{22G} tekstu.
+
+\subsubsection{Anotator}
+W dwa tygodnie od udostępnienia anotatora udało się:
+\begin{itemize}
+ \item zebrać \textbf{10260} anotacji godzin,
+ \item zaanotować \textbf{9313}\footnote{Dopuszczane jest by jedna godzina była
+ anotowana przez wielu unikalnych użytkowników. Stąd rozbieżność między
+ liczbą anotacji a zaanotowanymi godzinami.} z \textbf{10920} godzin.
+\end{itemize}
+Dane anotowano z \textbf{177} unikalnych urządzeń.
+Średni czas anotacji na urządzenie wyniósł \textbf{2,5} sekundy.
+
+Liczba urządzeń, z których anotowano godziny mszy świętych świadczy o
+zainteresowaniu społeczności katolickiej projektem automatycznego ekstraktora
+godzin mszy świętych. Entuzjazm udzielał się również w komentarzach na
+Facebook'u (komentarze pod postem z prośbą o anotowanie godzin mszy świętych).
+Średni czas anotacji, jak i liczba zaangażowanych użytkowników potwierdzają cechy anotatora
+wymienione
+w podrozdziale \ref{subsec:anotator} (szybkość, dostępność i wygoda użytkowania).
+\subsubsection{Regułowy ekstraktor danych}
+Regułowy ekstraktor danych był w stanie znaleźć godziny mszy świętych dla około
+\textbf{2600} parafii z \textbf{5177} parafii. Na małej próbce parafii ręcznie stwierdzono bardzo wysoką precyzję
+ekstrahowanych danych.
+
+\subsubsection{Klasyfikator godzin}
+Do ewaluacji ekstraktora godzin wykorzystano dane zebrane przez anotator. Z 9313 zaanotowanych
+godzin 80\% użyto do trenowania klasyfikatora, a 20\% do ewaluacji. Nie
+przeprowadzono optymalizacji parametrów.
+
+\noindent Otrzymano następujące wyniki:
+\begin{itemize}
+ \item \makebox[3.8cm][l]{wartość pokrycia} $= 0,884$
+ \item \makebox[3.8cm][l]{precyzja} $= 0,850$
+ \item \makebox[3.8cm][l]{F1\footnote{F1 to średnia harmoniczna z wartości pokrycia i precyzji.}} $= 0,884$
+ \item \makebox[3.8cm][l]{dokładność} $= 0,858$
+\end{itemize}
+Wyniki są obiecujące i z pewnością można je w przyszłości znacznie poprawić.
+ %\textbf{9313} anotacji godzin w \textbf{dwa tygodnie} od udostępnienia anotatora,
\chapter{Podsumowanie}
-Do napisania
+W pracy opisany został zrobiony przeze mnie system do ekstrakcji informacji
+godzin rozpoczęcia mszy świętych. Na początku przedstawiłem komponent
+odpowiedzialny za zbieranie informacji o parafiach. Następnie przybliżyłem
+metodę wyszukiwania adresów internetowych parafii. Potem dokładnie omówiłem
+architekturę pająka do pobierania stron parafialnych.
+W kolejnych rozdziałach krótko opisałem bibliotekę do konwersji tekstu,
+ekstraktor godzin oraz wyszukiwanie stron, na których z dużym prawdopodobieństwem
+znajdują się godziny mszy. Następnie omówiłem anotator służący do zbierania
+danych do uczenia maszynowego. Anotator dostępny jest pod adresem
+\url{msze.nsupdate.info}. Potem krótko opowiedziałem o regułowym ekstraktorze
+danych. W kolejnym rozdziale przedstawiłem model teoretyczny klasyfikatora
+godzin mszy. W szczególności wyprowadziłem równania na aktualizacje wag sieci
+neuronowej.
+Na końcu przedstawiłem informacje o wszystkich zebranych danych oraz wynikach
+anotatora, ekstraktora godzin mszy świętych i klasyfikatora godzin. Otrzymane
+rezultaty świadczą o sensowności projektu i zachęcają do jego dalszego rozwoju.
% \subsection{Ewaluacja wewnętrzna} %F1 score
% \subsection{Ewaluacja zewnętrzna} % w systemie webowym, użytkownicy
diff --git a/streszczenie.tex b/streszczenie.tex
index 392689f..622e625 100644
--- a/streszczenie.tex
+++ b/streszczenie.tex
@@ -1,4 +1,10 @@
\chapter*{Streszczenie}
-TODO
+Praca przedstawia proces tworzenia systemu ekstrakcji informacji o godzinach
+rozpoczęcia mszy świętych. Opisane zostają sposoby zbierania danych o polskich
+parafiach, w szczególności proces tworzenia pająków. Następnie pokazane zostają
+dwie metody ekstrakcji godzin rozpoczęcia mszy świętych: regułowa i oparta na
+uczeniu maszynowym. Większa uwaga zostaje poświęcona metodzie opartej na uczeniu
+maszynowym, która polega na wykorzystaniu klasyfikatora tekstu.
-\textbf{Słowa kluczowe:} ekstrakcja informacji
\ No newline at end of file
+\textbf{Słowa kluczowe:} ekstrakcja informacji, indeksowanie stron
+internetowych, klasyfikacja tekstu
\ No newline at end of file
diff --git a/wstep.tex b/wstep.tex
index 698dda2..df13a6b 100644
--- a/wstep.tex
+++ b/wstep.tex
@@ -1,2 +1,35 @@
\markboth{Wstęp}{Wstęp}
\addcontentsline{toc}{chapter}{Wstęp}
+\chapter*{Wstęp}
+Msza święta to najważniejsze duchowe wydarzenie w tygodniu chrześcijanina. Każdy wierzący katolik uczęszcza na niedzielną mszę świętą, a wielu również na msze święte w dni powszednie.
+Ze względu na rangę tego wydarzenia powstało kilka serwisów, które umożliwiają
+wyszukiwanie najbliższej godziny i miejsca mszy świętej. Z jednej strony
+powstały wyszukiwarki ogólnopolskie takie jak \url{kiedymsza.pl} lub
+\url{msze.info}. Wadą tych wyszukiwarek jest to, że wyświetlane godziny mszy
+świętych bardzo często są albo błędne, albo już nieaktualne.
+Z tego względu nie zdobyły one dużej popularności.
+Z drugiej strony powstały wyszukiwarki lokalne jak na
+przykład wyszukiwarka mszy świętych dla archidiecezji łódzkiej
+\url{archidiecezja.lodz.pl/wyszukiwarka-mszy-swietych/} lub aplikacja mobilna Drogowskaz\footnote{\url{www.aplikacjadrogowskaz.pl}}
+służąca do wyszukiwania mszy świętych w archidiecezji poznańskiej. Oczywistą
+wadą tych wyszukiwarek jest to, że obejmują małą liczbę polskich parafii.
+Oferują one za to bardzo wiarygodne informacje i są częściej aktualizowane.
+Zarówno
+ogólnopolskie, jak i lokalne wyszukiwarki mszy świętych zbierają swoje dane
+manualnie. Dane wpisują albo internauci, albo autorzy wyszukiwarek. W celu
+zasięgnięcia informacji dzwonią oni do parafii lub przepisują godziny mszy
+świętych ze stron parafialnych. Takie postępowanie jest bardzo czasochłonne i kosztowne.
+
+Niniejsza praca przedstawia system, który służy do automatycznego zbierania
+informacji o godzinach rozpoczęcia mszy świętych. W pierwszym rozdziale dokładnie opisano system
+ekstrakcji godzin mszy świętych. W drugim rozdziale przedstawiono osiągnięte
+rezultaty. W trzecim rozdziale podsumowano pracę.
+
+W momencie oddania pracy do druku system opisany w niniejszej pracy jest jedynym
+w Polsce automatycznym system ekstrakcji godzin mszy świętych.
+System przykuł uwagę jednego z
+autorów Drogowskazu. Zostały przeprowadzone wstępne rozmowy i jeśli system się
+sprawdzi, to być może będzie dostarczał dane dla aplikacji Drogwskaz.
+%%% Local Variables:
+%%% LaTeX-command: "latex -shell-escape"
+%%% End:
\ No newline at end of file