Wpis z mikrobloga

No elo swiry z #python #machinelearning #tensorflow
Mam takie zadanie do wykonania, jestem newbie i zastanawiam sie nad generalnym podejsciem/architektura:

Generowanie textu na podstawie podprzednio widzianych zdan oraz przekazanego kontekstu (slowa kluczowe).
W pierwszym przypadku jak rozumiem, moge zastosowac jakas rekurencyjna warstwe np LSTM, GRU, zmapowac zdania na chary i jako cel ustawic wybor kolejnej litery - zrobiem pare takich.
Ale w jaki sposob moge przekazac konktekst wypowiedzi? Np. uczenie generowania zdan ala Shakespear lub Nietzsche? Zalozmy ze dane wejsciowe bede mial dodatkowo otagowane taka statyczna flaga oznaczajaca autora.
  • 28
Nie bardzo rozumiem. Dowiązujesz kontekst do autora gdzie to są odrębne rzeczy. Żeby sieć się nauczyła pisać/mówić/cokolwiek jak ktoś konkretny to musisz w nią pakować dane z tego kogoś konkretnego. Żeby coś takiego osiągnąć to ja bym przepuścił trenowanie raz na danych z Shakespeara, zapisał stan sieci, drugi raz na danych z nietzshego i zapisał do odrębnego pliku. Wczytanie stanu sieci to nie jest jakieś drogie zadanie. A flagowanie to właśnie do
@matwiejblyat: to nie do końca jest tak, że mam 2 autorów - mam tagi do tekstu, słowa kluczowe - a więc średnio robić ręcznie osobną sieć na każdą możliwość. Dostałem radę, żeby zrobić to na zasadzie modelu seq2seq i to by nawet grało, tyle że pierwszy człon nie powinien być sekwencyjny ( w sensie, bez znaczenia w jakiej kolejności są tagi, liczy się ich obecność). Nie bardzo wiem jak z tego
@skrzacik320: jako h0, czyli? Ogólnie myślałem, żeby doklejać do litery wejściowej jakiś dodatkowy wektor określający autorów i jako dana wyjściowa patrzeć na rzeczywistą literę danego autora. Tylko nie wiem czy mi sieć nie zwariuje - czy tak się w ogóle da zrobić (,)
@wafel93: Przede wszystkim koduj całe wyrazy, a nie pojedyncze litery. W tym temacie poczytaj na temat BERT. Jak używasz Pytorch, to sprawdź sobie bibliotekę AllenNLP.

h0 to jest stan początkowy dla komórki rnn. Potem komórka wczytuje po kolei tokeny (czyli zakodowane znaki / wyrazy) i przy każdym zmienia ten stan na kolejny.

Najpierw skup się na tym jak działają LSTM, potem czym jest atencja (xD), a potem jak działa Transformer. Przeczytaj
@skrzacik320: przerobiłem prawie dwie książki z przykładami i nadal nie wiem jak dziala LSTM albo co to jest Transformer xDD
Mam do Ciebie dwa pytania, skoro tak:
1) Dlaczego lepiej jest kodować całe wyrazy niż litery? Generalnie nie mam zbyt dużo danych, ok 20k zdań z tagami opisującymi każde z nich - może powiem totalną głupotę - czy nie lepiej w takim wypadku stosować pojedyncze litery?
2) Dostałem początkowe info że
@wafel93: https://colah.github.io/posts/2015-08-Understanding-LSTMs/ - bardzo dobrze wytłumaczone i zilustrowane jak działają RNN, LSTM i GRU.

Kodować całe wyrazy jest lepiej po prostu dlatego, że wtedy sekwencja jest o wiele krótsza. Jak napiszesz zdanie "Ala ma kota" to zakodowanie tego wyrazami da Ci sekwencję o długości 3, a znakami 11. I odwrotnie, stworzenie tego zdania przez model będzie wymagało wygenerowania 3 wartości zamiast 11.

Seq2seq to inaczej architektura encoder-decoder, może pod tym hasłem
@skrzacik320: jeśli nadal masz cierpliwość do jakiegoś randoma z neta (za co super dziękuję swoją drogą), to poczytałem dalej i mam następujące przemyślenia:

1) mój problem nie jest klasycznym Seq2Seq -> oglądałem jakiegoś mądrego azjatę na YT i przedstawiał tam różne struktury RNN. Wspomniany wyżej zakłada, że Input jest sekwencyjny, jak w przypadku np. tłumaczenia zdań z angielkiego na polski (w wielkim uproszczeniu jak rozumiem). Powiedział także o modelu One2Many, który
@wafel93: Ok, zacznijmy od Embeddings, a później przejdziemy do reszty. To, co wcześniej o krótszym kodowaniu nadal ma znaczenie, ale to było trochę nadmierne uproszczenie.

Embeddings to przypisanie każdemu elementowi (w tym wypadku literze albo słowu) wektora n liczb. Można na to patrzeć, jak na współrzędną tego elementu w n-wymiarowej przestrzeni. Na początku, gdy inicjujemy losowo, te elementy są porozrzucane w tej przestrzeni chaotycznie i bez sensu.

W trakcie treningu te
@wafel93: Twój zestaw danych jak rozumiem wygląda tak:

(autor, zdanie) -> (następne zdanie)

Jeśli kodujesz całe słowa, to możesz po prostu scalić autora i zdanie w jeden string, tak że słowo reprezentujące autora będzie zawsze na pierwszym miejscu. Więc twój przykład będzie wyglądał tak:

(Mickiewicz Litwo ojczyzno moja) -> (Ty jesteś jak zdrowie)

Jeśli pierwszym słowem będzie zawsze autor, to będzie ono czymś w rodzaju stanu początkowego. Jeśli oprócz autora chcesz
@skrzacik320: a więc może wyłożę karty na stół, bo to z autorami to było jedynie porównanie - na takich przykładach ogarniałem Seq2Seq.

Mój zbiór danych to komentarze do zdjęć - każde zdjęcie jest otagowane kilkoma słowami kluczowymi (np. animal, ecology). Same komentarze są raczej jednozdaniowe i mało skomplikowane (Instagram :P), aczkolwiek problematyczny moze być fakt, że jest w nich dużo emotek (które być może wyfiltruję, jeśli okaże się to zbyt złożony
@wafel93: Aaaa to rozumiem :-) Rzeczywiście to nie jest seq2seq. Na początku możesz spróbować najprościej jak się da, bez żadnych rnn. Po prostu robisz sieć, która koduje te tagi w multi-hot i wypluwa wektory ze zdaniami o stałej długości. Jak mówisz, zdania są krótkie, więc mogłoby to nawet zadziałać. Np. wyjściem twojej sieci byłby tensor o rozmiarze [batch, length, token] gdzie batch to liczba przykładów, length to maksymalna długość zdania, a
@skrzacik320: wlasnie przerabiam o co chodzi w embeddings i faktycznie, znalem jedynie wierzcholek gory lodowej xD

W zasugerowanym przykladzie bez RNN, jak rozumiem, zakladam kodowanie literowe.
Input = array[200], gdzie 1 sa tylko uzywane tagi, np. input[34] = 1, bo ecology tam zakodowalem.
Przepuszczam calosc przez warstw Dense tratatata

iii

co do wyjscia, zalezy jak bym reprezentowal litery, czy jako one-hot czy indexowo. Jesli one-hot, to wyjsciem bylby vector [length, token]
@wafel93: Tak, mniej więcej o to chodzi. Jeśli chodzi o wyjście, to nie rób tego tym jak to określiłeś indeksowaniem. Bo litera to jest zmienna kategoryczna, a tam próbowałbyś ją generować jak zmienną ciągłą.

Jak już zrobisz wszystko tak, że będzie działało i się uczyło, to będziesz mógł eksperymentować. Np zamiast warstwy wyjściowej wsadzić kilka warstw rnn. Potem dodać atencję. Albo zamiast wejścia multi-hot zrobić embedding-bag (zsumowane embeddings). Albo zrobić z
@skrzacik320: Okej, baaardzo mi pomoglas, serio :) Zabieram sie za przygotowanie danych i implementacje. Jak to mawiaja, niechaj Ci latajacy potwor spageti w bombelkach wynagrodzi.

PS: Bede mogl sie w przyszlosci jeszcze Cie podpytac o te rnn? Bo prawde mowiac, nadal nie mam pojecia jak to osadzic w tej architekturze ()
@skrzacik320: Hello maj frend! Klece sobie wersje minimalna, ktora ma sie nauczyc wypluwac zdania na podstawie przekazanych tagow. Wlasnie skonczylem obrabiac dane (nie spodziewalem sie, ze to tyle czasu zajmie - jeszcze musialem jezyki odfiltrowac itd :/). Obecny uklad wyglada tak:

input - one hot encoded tags : [1,1,0,0 ... 0] - dlugosc to 200, od poczatku sa najczesciej uzywane (jako ciekawostka powiem Ci, ze calkiem wysoko w tematach ekologicznych jest