2017-02-02 28 views
6

Mam kodowane LSTM sequence to sequence uczenia się w kamerze samodzielnie przy użyciu wiedzy uzyskanej z samouczków internetowych i moje własne intuicje. Przekształciłem mój przykładowy tekst w sekwencje, a następnie dopełniono przy pomocy funkcji pad_sequence w keras.Jak powinniśmy podkładać sekwencje tekstu w kerasach za pomocą pad_sequences?

from keras.preprocessing.text import Tokenizer,base_filter 
from keras.preprocessing.sequence import pad_sequences 

def shift(seq, n): 
    n = n % len(seq) 
    return seq[n:] + seq[:n] 

txt="abcdefghijklmn"*100 

tk = Tokenizer(nb_words=2000, filters=base_filter(), lower=True, split=" ") 
tk.fit_on_texts(txt) 
x = tk.texts_to_sequences(txt) 
#shifing to left 
y = shift(x,1) 

#padding sequence 
max_len = 100 
max_features=len(tk.word_counts) 
X = pad_sequences(x, maxlen=max_len) 
Y = pad_sequences(y, maxlen=max_len) 

Po starannie kontroli znalazłem mój wyściełane sekwencja wygląda tak

>>> X[0:6] 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3], 
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], 
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5], 
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4], 
     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7]], dtype=int32) 
>>> X 
array([[ 0, 0, 0, ..., 0, 0, 1], 
     [ 0, 0, 0, ..., 0, 0, 3], 
     [ 0, 0, 0, ..., 0, 0, 2], 
     ..., 
     [ 0, 0, 0, ..., 0, 0, 13], 
     [ 0, 0, 0, ..., 0, 0, 12], 
     [ 0, 0, 0, ..., 0, 0, 14]], dtype=int32) 

Czy wyściełane sekwencja przypuszczać, aby wyglądać tak? Oprócz ostatniej kolumny w tablicy pozostałe są zerami. Sądzę, że popełniłem jakiś błąd polegający na dopełnianiu tekstu do sekwencji, a jeśli tak, to czy możesz mi powiedzieć, gdzie popełniłem błąd?

Odpowiedz

6

Jeśli chcesz tokenize przez char, można to zrobić ręcznie, to nie jest zbyt skomplikowane:

najpierw zbudować słownictwo dla swoich bohaterów:

txt="abcdefghijklmn"*100 
vocab_char = {k: (v+1) for k, v in zip(set(txt), range(len(set(txt))))} 
vocab_char['<PAD>'] = 0 

Spowoduje to powiązanie odrębnej liczby dla każdej postaci w txt. Postać o indeksie 0 powinna być zachowana dla dopełnienia.

Posiadanie odwrotnego słownictwa będzie przydatne do dekodowania danych wyjściowych.

rvocab = {v: k for k, v in vocab.items()} 

Gdy masz to można najpierw podzielić tekst w sekwencje, że chcesz mieć sekwencje długości seq_len = 13:

[[vocab_char[char] for char in txt[i:(i+seq_len)]] for i in range(0,len(txt),seq_len)] 

twoje wyjście będzie wyglądać następująco:

[[9, 12, 6, 10, 8, 7, 2, 1, 5, 13, 11, 4, 3], 
[14, 9, 12, 6, 10, 8, 7, 2, 1, 5, 13, 11, 4], 
..., 
[2, 1, 5, 13, 11, 4, 3, 14, 9, 12, 6, 10, 8], 
[7, 2, 1, 5, 13, 11, 4, 3, 14]] 

Pamiętaj, że ostatnia sekwencja nie ma tej samej długości, możesz ją odrzucić lub przesunąć sekwencję do max_len = 13, doda do niej 0.

Można budować swoje cele Y ten sam sposób poprzez przesuwanie wszystko o 1. :-)

Mam nadzieję, że to pomaga.

3

Problem jest w tym wierszu:

tk = Tokenizer(nb_words=2000, filters=base_filter(), lower=True, split=" ") 

Po ustawieniu takiego podziału (przez " "), ze względu na charakter danych, dostaniesz każdą sekwencję składającą się z jednego słowa. Dlatego twoje wyściełane sekwencje mają tylko jeden niezerowy element. Aby zmienić tę okazję:

txt="a b c d e f g h i j k l m n "*100 
+0

Dziękujemy za wskazanie błędu, ale jaki jest najlepszy sposób rozwiązania tego problemu. Dokumenty w [keras] (https://keras.io/preprocessing/text/#tokenizer) są bardzo nieprecyzyjne. – Eka

+0

Jakie są twoje sekwencje oddzielone? –

+0

Moja sekwencja wygląda mniej więcej tak: 'abcdefghijklmnabcdefghijklmn ..... mn' Chcę go oddzielić jako pojedyncze litery 'a b c d e f g h i j k l m n ...' który jest jak znaki (sekwencja znaków do nauki sekwencji) – Eka