przemowoAnalizator/readme.md

95 lines
5.0 KiB
Markdown
Raw Normal View History

2020-01-09 21:13:45 +01:00
# 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.
2020-01-09 21:15:47 +01:00
Sprawdzamy czy nasz tekst nadaje się do dalszej analizy poprzez binarną klasyfikację czy jest to marsz, przemowa lub nie.
2020-01-09 21:13:45 +01:00
Moje dane pochodzą głównie ze strony http://www.sovmusic.ru/english/, gdzie ktoś przez wiele lat gromadził teksty komunistycznych pieśni.
2020-01-09 21:15:47 +01:00
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.
2020-01-09 21:13:45 +01:00
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`
2020-01-09 21:15:47 +01:00
Przykłady innych tekstów, normalnych piosenek znalazłem na https://github.com/Lyrics/lyrics
2020-01-09 21:13:45 +01:00
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
2020-01-09 21:15:47 +01:00
```sh
2020-01-09 21:13:45 +01:00
$python3 stats.py
Precision: 0.9636363636363636
Recall: 1.0
f1: 0.9814814814814815
2020-01-09 21:15:47 +01:00
```
Żeby samemu wszsytko włączyć:
```sh
2020-01-09 21:17:15 +01:00
$pip3 install -r requirements.txt
2020-01-09 21:15:47 +01:00
$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: