94 lines
4.9 KiB
Markdown
94 lines
4.9 KiB
Markdown
# 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
|
|
$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: |