2016-06-14 31 views
6

Sto eseguendo un BLSTM basato su IMDB example, ma la mia versione non è una classificazione, piuttosto una previsione di sequenza per le etichette. Per semplicità, puoi trattarlo come un modello di codifica POS. Gli input sono frasi di parole, gli output sono tag. La sintassi utilizzata nell'esempio differisce leggermente nella sintassi dalla maggior parte degli altri esempi di Keras in quanto non utilizza model.add ma avvia una sequenza. Non riesco a capire come aggiungere un livello di mascheramento in questa sintassi leggermente diversa.mascheramento per keras BLSTM

Ho eseguito il modello e l'ho testato, e funziona benissimo ma è la previsione e la valutazione della precisione degli 0, che sono il mio padding. Ecco il codice:

from __future__ import print_function 
import numpy as np 
from keras.preprocessing import sequence 
from keras.models import Model 
from keras.layers.core import Masking 
from keras.layers import TimeDistributed, Dense 
from keras.layers import Dropout, Embedding, LSTM, Input, merge 
from prep_nn import prep_scan 
from keras.utils import np_utils, generic_utils 


np.random.seed(1337) # for reproducibility 
nb_words = 20000 # max. size of vocab 
nb_classes = 10 # number of labels 
hidden = 500 # 500 gives best results so far 
batch_size = 10 # create and update net after 10 lines 
val_split = .1 
epochs = 15 

# input for X is multi-dimensional numpy array with IDs, 
# one line per array. input y is multi-dimensional numpy array with 
# binary arrays for each value of each label. 
# maxlen is length of longest line 
print('Loading data...') 
(X_train, y_train), (X_test, y_test) = prep_scan(
    nb_words=nb_words, test_len=75) 

print(len(X_train), 'train sequences') 
print(int(len(X_train)*val_split), 'validation sequences') 
print(len(X_test), 'heldout sequences') 

# this is the placeholder tensor for the input sequences 
sequence = Input(shape=(maxlen,), dtype='int32') 

# this embedding layer will transform the sequences of integers 
# into vectors 
embedded = Embedding(nb_words, output_dim=hidden, 
        input_length=maxlen)(sequence) 

# apply forwards LSTM 
forwards = LSTM(output_dim=hidden, return_sequences=True)(embedded) 
# apply backwards LSTM 
backwards = LSTM(output_dim=hidden, return_sequences=True, 
       go_backwards=True)(embedded) 

# concatenate the outputs of the 2 LSTMs 
merged = merge([forwards, backwards], mode='concat', concat_axis=-1) 
after_dp = Dropout(0.15)(merged) 

# TimeDistributed for sequence 
# change activation to sigmoid? 
output = TimeDistributed(
    Dense(output_dim=nb_classes, 
      activation='softmax'))(after_dp) 

model = Model(input=sequence, output=output) 

# try using different optimizers and different optimizer configs 
# loss=binary_crossentropy, optimizer=rmsprop 
model.compile(loss='categorical_crossentropy', 
       metrics=['accuracy'], optimizer='adam') 

print('Train...') 
model.fit(X_train, y_train, 
      batch_size=batch_size, 
      nb_epoch=epochs, 
      shuffle=True, 
      validation_split=val_split) 

UPDATE:

ho fuse questo PR e ottenuto che funziona con mask_zero=True nello strato di incorporamento. Ma ora mi sto rendendo conto dopo aver visto prestazioni terribili del modello che avrei anche dovuto mascherare nell'output, altri hanno suggerito di utilizzare sample_weight invece nella riga model.fit. Come posso fare questo per ignorare gli 0?

UPDATE 2:

così ho letto this e capito il sample_weight come una matrice di 1 e 0. Ho pensato che potesse funzionare, ma la mia accuratezza si blocca attorno a% 50, e ho appena scoperto che sta cercando di prevedere le parti imbottite, ma non le prediremo come 0 ora, come era il problema prima di usare sample_weight.

codice attuale:

from __future__ import print_function 
import numpy as np 
from keras.preprocessing import sequence 
from keras.models import Model 
from keras.layers.core import Masking 
from keras.layers import TimeDistributed, Dense 
from keras.layers import Dropout, Embedding, LSTM, Input, merge 
from prep_nn import prep_scan 
from keras.utils import np_utils, generic_utils 
import itertools 
from itertools import chain 
from sklearn.preprocessing import LabelBinarizer 
import sklearn 
import pandas as pd 


np.random.seed(1337) # for reproducibility 
nb_words = 20000 # max. size of vocab 
nb_classes = 10 # number of labels 
hidden = 500 # 500 gives best results so far 
batch_size = 10 # create and update net after 10 lines 
val_split = .1 
epochs = 10 

# input for X is multi-dimensional numpy array with syll IDs, 
# one line per array. input y is multi-dimensional numpy array with 
# binary arrays for each value of each label. 
# maxlen is length of longest line 
print('Loading data...') 
(X_train, y_train), (X_test, y_test), maxlen, sylls_ids, tags_ids, weights = prep_scan(nb_words=nb_words, test_len=75) 

print(len(X_train), 'train sequences') 
print(int(len(X_train) * val_split), 'validation sequences') 
print(len(X_test), 'heldout sequences') 

# this is the placeholder tensor for the input sequences 
sequence = Input(shape=(maxlen,), dtype='int32') 

# this embedding layer will transform the sequences of integers 
# into vectors of size 256 
embedded = Embedding(nb_words, output_dim=hidden, 
        input_length=maxlen, mask_zero=True)(sequence) 

# apply forwards LSTM 
forwards = LSTM(output_dim=hidden, return_sequences=True)(embedded) 
# apply backwards LSTM 
backwards = LSTM(output_dim=hidden, return_sequences=True, 
       go_backwards=True)(embedded) 

# concatenate the outputs of the 2 LSTMs 
merged = merge([forwards, backwards], mode='concat', concat_axis=-1) 
# after_dp = Dropout(0.)(merged) 

# TimeDistributed for sequence 
# change activation to sigmoid? 
output = TimeDistributed(
    Dense(output_dim=nb_classes, 
      activation='softmax'))(merged) 

model = Model(input=sequence, output=output) 

# try using different optimizers and different optimizer configs 
# loss=binary_crossentropy, optimizer=rmsprop 
model.compile(loss='categorical_crossentropy', 
       metrics=['accuracy'], optimizer='adam', 
       sample_weight_mode='temporal') 

print('Train...') 
model.fit(X_train, y_train, 
      batch_size=batch_size, 
      nb_epoch=epochs, 
      shuffle=True, 
      validation_split=val_split, 
      sample_weight=weights) 
+0

È una vecchia domanda ma l'hai risolto? Sono all'incirca allo stesso stadio ... Ho scoperto che [l'accuratezza non tiene conto di sample_weight] (https://github.com/fchollet/keras/issues/1642) e secondo i miei test né il mascheramento (in realtà l'uso del mascheramento produce un valore di precisione diverso che non riuscivo ancora a elaborare). Probabilmente finirò usando l'API funzionale per costruire un secondo risultato con la precisione. – jdehesa

+0

Rivedere questa domanda e semplificarla in relazione all'attuale codice Keras sarebbe molto apprezzata. – Seanny123

risposta

1

avete risolto questo problema? Non mi è molto chiaro come il tuo codice tratti i valori e gli indici di parole imbottiti. Che dire di lasciar indici di parole iniziare da 1 e la definizione di

embedded = Embedding(nb_words + 1, output_dim=hidden, 
       input_length=maxlen, mask_zero=True)(sequence) 

invece di

embedded = Embedding(nb_words, output_dim=hidden, 
       input_length=maxlen, mask_zero=True)(sequence) 

in base alle https://keras.io/layers/embeddings/?

Problemi correlati