Generator; zobacz też: generator limeryków i niezdeterminowanie przekładu .
Tym razem będzie stricte technicznie.
Wynurzeń filozoficznych (jak przy
niezdeterminowaniu przekładu) brak.
Miało to działać mniejwięcej tak:
Przymiotnik rzeczownik[-rym1], przymiotnik rzeczownik[-rym2], przymiotnik rzeczownik[-rym1], przymiotnik rzeczownik[-rym2].
Jednym z moich poważniejszych zainteresowań jest dziedzina sztucznej inteligencji zwana przetwarzaniem języka angielskiego, lub w skrócie NLP (natural language programming). To na kanwie tych zainteresowań zająłem się w ogóle pisaniem generatorów, moje poprzednie (opublikwoane) generatory jednak tak na prawdę nie korzystały w pełni z narzędzi jakie oferuje informatyka, były raczej prostą implementacją gramatyk generatywnych, co było jednak zamierzone. Od dawna jednak eksperymentowałem z programowaniem generatorów wykorzystujących korpusy językowe.
O korpusy języka polskiego przez pewien czas było stosunkowo trudno. Istniał co prawda korpus polszczyzny lat 60 IPI PAN, ale narzędzia dla niego były przeznaczone głównie do bezpośredniego przeglądania i przeszukiwania korpusu, a nie do pisania generatorów. Sytuację poprawiło jednak pojawienie się Pythonowej biblioteki NLTK (Natural Language Toolkit), w skład której weszło wiele korpusów, w tym właśnie korpus polszczyzny lat 60.
Co ważne, korpusy o których mówią to korpusy z oznaczeniami gramatycznymi. Oznacza to że w przeciwieństwie do na przykład bazy danych portalu Wolne Lektury, na których bazuje leśmianator, każde słowo ma tu oznaczenia, jaką jest częścią mowy i w jaką ma formę. W wersji korpusu wchodzącej w skład NLTK dostępna jest w szczególności funkcja nltk.corpus.pl196x.tagged_words(), zwracająca listę wszystkich słów korpusu w formie par (słowo, oznaczenia).
Uruchomiłem interpteter Pythona, zaimportowałem bibliotekę NLTK i przefiltrowałem korpus, uzyskując dwie listy słów:
rzeczowników w mianowniku liczby pojedyńczej, oraz przymiotników w tej samej formie gramatycznej.
Używając wyrażenia regularnego dopasowującego sylabę przefiltrowałem te listy zostawiając tylko słowa czterosylabowe
(tj. mające dokładnie 4 dopasowania wyrażenia regularnego).
Następnie pozbyłem się duplikatów (rzutując na zbiór i z powrotem na listę: list(set(…))
),
uprzednio zamieniając wszystko na małe litery:
map(lambda slowo: unicode(slowo, 'utf-8').lower(), d)
Ponieważ wiersze miały się rymować napisałem prostą funkcję wyodrębniającą rym:
lambda slowo: re.compile(
ur"[aoieyuąę][^aoieyuąęó]*(?:(?:i?[aoeyuąęó])|i)[^aoieyuąęó]*$",
re.I | re.U
).findall(slowo)[0]
Rzeczowniki podzieliłem dalej na grupy według rymu i wygenerowałem sobie z nich plik JS z całą strukturą w formacie JSON. Z przymiotnikami postąpiłem podobnie, tylko zamiast według rymu podzieliłem je na męskie, żeńskei i nijakie według oznaczeń gramatycznych. Rzeczowniki też na takie grupy podzieliłem, ale już ręcznie (trzeba było uwzględnić sytuację, gdy ten sam rym zawiera zarówno rzeczowniki żeńskie, jak i męskie żeńskiej deklinacji).
Potem uruchomiłem interpreter Node.js i zaimportowałem strukturę z rzeczownikikami i policzyłem w kilku liniach kodu ilość słów dla każdego rodzaju rzeczowników. Po odrobinie ekwilibrystyki z JavaScriptem i edytorem kodu uzyskałem ostateczną strukturę danych:
var rzeczowniki = {
m: [91, {
'alizm': […],
'unek': […],
'ony': […],
etc.
}],
f: [248, {
etc.
}],
n: [402, {
etc.
}]
};
(i oczywiście drugą, nieco prostszą, dla przymiotników).
Skrypt wybiera słowa, najpierw rzeczownik, albo losowy, albo zgodny z zadaną formą, a potem przymiotnik w tym samym rodzaju gramatycznym. Konstytuuje to wers. Dla wersów 1 i 2 strofki rodzaj i rym jest losowy, dla wersów 3 i 4 zgodny z odpowiednio wersem 1. i 2. Każdy wers dostaje na końcu przecinek, a ostatni kropkę, lub inny zdefiniowany znak. Pierwsza litera pierwszego wersu jest zamieniana na wielką. Ostatecznie moduł generujący zwraca strofkę wiersza w formie tablicy czteroelementowej.
Plik HTML generatora zawiera funkcję wywołującą generator dwa razy i generującą w ten sposób dwie strofki, pierwszą ze średnikiem na końcu, drugą z domyślną kropką. Wersy są w nich następnie łączone <br>'ami, a same strofki łączone są znacznikiem <p>. Tyle.
Efekt możecie podziwiać tutaj.
Wybaczcie, tym razem ładnych tabelek nie zrobię, bo słów w każdej kategorii jest po kilkaset. Zamiast tego link do źródła skryptu generującego: rymgen.js (utf-8).
No chyba, że bardzo chcecie: .
ja, bo ja
© | Copyright © 2012 J.B.Jagiełło, wszelkie prawa do tego tekstu i generatora zastrzeżone. |
---|