2016-05-18 2 views
11

Je suis relativement nouveau dans les réseaux de neurones, alors excusez mon ignorance. J'essaie d'adapter l'exemple de keras BLSTM here. L'exemple lit dans les textes et les classifie comme 0 ou 1. Je veux un BLSTM qui fait quelque chose très semblable au tag POS, bien que des extras comme la lemmatisation ou d'autres fonctionnalités avancées ne soient pas nécessaires, je veux juste un modèle basique. Mes données sont une liste de phrases et chaque mot reçoit une catégorie 1-8. Je veux former un BLSTM qui peut utiliser ces données pour prédire la catégorie de chaque mot dans une phrase invisible.keras BLSTM pour l'étiquetage de séquence

par exemple. input = ['The', 'dog', 'est', 'red'] donne output = [2, 4, 3, 7]

Si l'exemple de keras n'est pas le meilleur itinéraire, je suis ouvert à d'autres suggestions

J'ai actuellement ceci:

'''Train a Bidirectional LSTM.''' 

from __future__ import print_function 
import numpy as np 
from keras.preprocessing import sequence 
from keras.models import Model 
from keras.layers import Dense, Dropout, Embedding, LSTM, Input, merge 
from prep_nn import prep_scan 


np.random.seed(1337) # for reproducibility 
max_features = 20000 
batch_size = 16 
maxlen = 18 

print('Loading data...') 
(X_train, y_train), (X_test, y_test) = prep_scan(nb_words=max_features, 
               test_split=0.2) 
print(len(X_train), 'train sequences') 
print(len(X_test), 'test sequences') 

print("Pad sequences (samples x time)") 
# type issues here? float/int? 
X_train = sequence.pad_sequences(X_train, value=0.) 
X_test = sequence.pad_sequences(X_test, value=0.) # pad with zeros 

print('X_train shape:', X_train.shape) 
print('X_test shape:', X_test.shape) 

# need to pad y too, because more than 1 ouput value, not classification? 
y_train = sequence.pad_sequences(np.array(y_train), value=0.) 
y_test = sequence.pad_sequences(np.array(y_test), value=0.) 

print('y_train shape:', X_train.shape) 
print('y_test shape:', X_test.shape) 

# 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 128 
embedded = Embedding(max_features, 128, input_length=maxlen)(sequence) 

# apply forwards LSTM 
forwards = LSTM(64)(embedded) 
# apply backwards LSTM 
backwards = LSTM(64, go_backwards=True)(embedded) 

# concatenate the outputs of the 2 LSTMs 
merged = merge([forwards, backwards], mode='concat', concat_axis=-1) 
after_dp = Dropout(0.5)(merged) 
# number after dense has to corresponse to output matrix? 
output = Dense(17, activation='sigmoid')(after_dp) 

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

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

print('Train...') 
model.fit(X_train, y_train, 
      batch_size=batch_size, 
      nb_epoch=4, 
      validation_data=[X_test, y_test]) 

X_test_new = np.array([[0,0,0,0,0,0,0,0,0,12,3,55,4,34,5,45,3,9],[0,0,0,0,0,0,0,1,7,65,34,67,34,23,24,67,54,43,]]) 

classes = model.predict(X_test_new, batch_size=16) 
print(classes) 

Ma sortie est la bonne dimension, mais me donne 0-1 à virgule flottante. Je pense que c'est parce qu'il est toujours à la recherche de classifications binaires. Quelqu'un sait comment réparer ceci?

SOLVED

Assurez-vous que les étiquettes sont chacun des tableaux binaires:

(X_train, y_train), (X_test, y_test), maxlen, word_ids, tags_ids = prep_model(
    nb_words=nb_words, test_len=75) 

W = (y_train > 0).astype('float') 

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.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', 
       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=W) 
+0

Pourriez-vous télécharger un petit échantillon de vos données? Cela aide à mieux comprendre le fonctionnement du modèle. Si ce n'est pas possible, pourriez-vous expliquer un peu à quoi ressemblent vos données brutes et ce que vous avez fait pour le prétraitement des données avant d'alimenter le modèle? –

Répondre

4

Solved. Le principal problème était de remodeler les données pour les catégories de classification en tant que tableaux binaires. Également utilisé TimeDistributed et définissez return_sequences sur True.

+0

est-il possible que vous ajoutiez le code de travail? thx – PSNR

+0

Bien sûr, juste voir les modifications ci-dessus. – ChrisDH

+0

Merci! Quand nous utilisons 'mask_zero = True' dans la couche d'intégration, je suppose que toutes les couches suivantes ignoreront cette classe pour le calcul de la perte, de la précision, etc. Et je suppose que le 'nb_classes' dans le calque de sortie devrait être # de classe + 1 (c'est-à-dire, pour le problème de classification binaire c'est 3)? Merci encore! – PSNR