# Czy tekst jest rewolucyjnym marszem wojennym lub przemową? Od dawna zastanawiałem się nad stworzeniem małej gry w której wcielamy się w rolę propagandzisty totalitarnego państwa (takiego jak fikcyjna Arstotzka z Papers Please). Gra miałaby polegać na pisaniu odpowiednich przemów i tekstów marszy zależenie od sytuacji. W ramach projektu postanowiłem spróbować wykonać chociaż jeden z komponentów. Sprawdzamy czy nasz tekst nadaje się do dalszej analizy poprzez binarną klasyfikację czy jest to marsz, przemowa lub nie. Moje dane pochodzą głównie ze strony http://www.sovmusic.ru/english/, gdzie ktoś przez wiele lat gromadził teksty komunistycznych pieśni. Drugim, mniejszym źródłem była strona na której umieszczone zostały przetłumaczone na angielski rozkazy i pisma Stalina z drugiej wojny światowej. https://www.marxists.org/reference/archive/stalin/works/decades-index.htm. Jest tego dużo, więc zrobiłem bota do ściągania danych `stalin_war_crawler.py` i `stalin_trockizm_crawler.py` Przykłady innych tekstów, normalnych piosenek znalazłem na https://github.com/Lyrics/lyrics Największym problemem okazał się format zbioru piosenek z rosyjskiej strony - jest to ogromny, tabelkowy dokument .html, z którego było cięzko wyciągnąć teksty. Do tego, teksty są w różnych językach - trzeba było je znormalizować do jednego języka. Wybrałem angielski, bo google translate najlepiej działa na tym języku. W celu masowego tłumaczenia napisałem skrypt (`piosenki/translate.py`) wyciągający teksty i używający popularnego exploita w google translate poprzez bibliotekę `googletrans` do pythona (`pip3 install googletrans`). Przetłumaczone teksty są zapisywane do osobnych plików. To samo musiałem zrobić z innymi tekstami, bo twórca zbioru danych był wielkim fanem niemieckiego metalu i około 1/3 tekstów była po niemiecku. Skrypt `vowpalize.py` wyciąga teksty, usuwa znaki nowych linii oraz znaki interpunkcyjne zostawiając tylko słowa. Następnie taki tekst jest tokenizowany i lematyzowany przez Spacy. Lista zlematyzowanych słów jest zapisywana do formatu vowpala. Marsze mają label +1 a inne teksty -1. Bez czyszczenia i lematyzowania wyniki były około 2-3 razy gorsze. Do trenowania modelu w vowpalu użyłem kilku podejść: 1. `vw --binary vowpal.txt --passes 20 -c -k -f model.model`, ale average loss na zestawie dev wynosił ponad 4%. 2. `vw --binary vowpal.txt --passes 5 -c -k -f model.model --loss_function logistic -b 24 --nn 20` dodając ukryte warstwy do sieci neuronowej udało mi się zejśc do około 2% average loss. Dodanie opcji `--inpass`, która dodaje połaczenie z neuronu na wejściu do wyjścia pogorszyła wyniki average loss o 1 punkt procentowy. Zmiana funckcji straty na hinge także znacznie pogarsza wyniki. Nim więcej warstw ukrytych w sieci tym lepsze wyniki, aż do granicy 20. Nim mniejszy weight array tym gorzej (`-b`) Liczba przejśc nie wpływa na wynik. Zostawiam niski żeby szybciej trenowało i nie overfitowało Dodatkowe features takie jak np liczba nazw geograficznych nie podniosłaby znacznie dokładności a mogłaby być myląca. Dla przykładu, poniższe fragmenty starego polskiego marszu "za Bug" zawierają dużo nazw geograficznych ``` Warczy próg Dniepru, pomrukuje Dźwina, Wyje stepami polska Ukraina, Dyszy niechęcią bagniste Polesie, Burzami grożą naddniestrzańskie skały, Lesista Litwa dąsa się i ćmi się Na nasz pochód opieszały. Wodzu nasz Janie! białe orły żebrzą Ogniem Grochowa i Wawru napadem, Niech się coprędzej brzegi Bugu srebrzą Uderzcie w bębny, zagrajcie nam w rogi. Uderzcie w bębny, zagrajcie nam w rogi, Za Bug, za Bug, za Bug, za Bug, za Bug, za Bug! Niech lotne serce nie wyprzedza nogi, ``` Oraz popularna szanta "hiszpańskie dziewczyny" ``` Niedługo ujrzymy znów w dali Cape Deadman I Głowę Baranią sterczącą wśród wzgórz, I statki stojące na redzie przed Plymouth. Klarować kotwicę najwyższy czas już. I smak waszych ust, hiszpańskie dziewczyny, ... I znów białe żagle na masztach rozkwitną, Kurs szyper wyznaczy do Portland i Wright, I znów stara łajba potoczy się ciężko Przez fale w kierunku na Beachie, Fairlee Light. Zabłysną nam bielą skał zęby pod Dover I znów noc w kubryku wśród legend i bajd. Powoli i znojnie tak płynie nam życie Na wodach i w portach przy South Foreland Light. ``` Mimo wielu nazw w obu tekstach, są one klasyfikowane na dwie różne klasy. Dodanie feature z liczbą nazw mogłoby wprowadzić program w błąd. Ostatecznie wyniki ```sh $python3 stats.py Precision: 0.9636363636363636 Recall: 1.0 f1: 0.9814814814814815 ``` Żeby samemu wszsytko włączyć: ```sh $pip3 install -r requirements.txt $python3 vowpalize.py $python3 prepareTestFiles.py $vw --binary vowpal.txt --passes 5 -c -k -f model.model --loss_function logistic -b 24 --nn 20 $vw -t -i model.model -p pred.pred test.txt $python3 stats.py ``` Jest zbiór test i dev. Co ciekawe, na test wychodzą lepsze wyniki niż na dev :joy: