1

I haved trained a named entity recognition model, after saving it and loading it back it is giving correct prediction on the same IPython session, but whenever I close the session and open it again, the loaded model prediction randomly. Can you help me with that?

I have saved the model in hdf5 format using:

Model.save("filename")

And I am loading it using:

Model.load_model("filename")

here is my full code

import pandas as pd
import numpy as np
import os
from keras.preprocessing.sequence import pad_sequences
from keras.utils import to_categorical
from sklearn.model_selection import train_test_split
from keras.models import Model, Input,load_model
from keras.layers import LSTM, Embedding, Dense, TimeDistributed, Dropout,  
Bidirectional
from nltk import pos_tag, word_tokenize,sent_tokenize



data = pd.read_csv("E:\ml tut\entity recognition\exdataset.csv", 
encoding="latin1")
data = data.fillna(method="ffill")
words = list(set(data["Word"].values))
words.append("ENDPAD")
n_words = len(words); n_words

tags = list(set(data["Tag"].values))
n_tags = len(tags); n_tags

class SentenceGetter(object):

    def __init__(self, data):
        self.n_sent = 1
        self.data = data
        self.empty = False
        agg_func = lambda s: [((w, p), t) for w, p, t in 
                 zip(s["Word"].values.tolist(),s["POS"].values.tolist(),     
                                             s["Tag"].values.tolist())]
        self.grouped = self.data.groupby("Sentence #").apply(agg_func)
        self.sentences = [s for s in self.grouped]

    def get_next(self):
        try:
            s = self.grouped["Sentence: {}".format(self.n_sent)]
            self.n_sent += 1
            return s
        except:
            return None

getter = SentenceGetter(data)

sent = getter.get_next()
print(sent)

sentences = getter.sentences

max_len = 50
word2idx = {w: i for i, w in enumerate(words)}
tag2idx = {t: i for i, t in enumerate(tags)}





input = Input(shape=(max_len,))
model = Embedding(input_dim=n_words, output_dim=50, input_length=max_len) 
       (input)

model = Dropout(0.1)(model)

model = Bidirectional(LSTM(units=100, return_sequences=True, 
recurrent_dropout=0.1))(model)

out = TimeDistributed(Dense(n_tags, activation="softmax"))(model)  

if os.path.exists('my_model.h5'):
    print("loading model")
    model = load_model('my_model.h5')
else:
    print("training model")
    X = [[word2idx[w[0][0]] for w in s] for s in sentences]
    X = pad_sequences(maxlen=max_len, sequences=X, padding="post", 
    value=n_words - 1)
    y = [[tag2idx[w[1]] for w in s] for s in sentences]
    y = pad_sequences(maxlen=max_len, sequences=y, padding="post", 
    value=tag2idx["O"])
    y = [to_categorical(i, num_classes=n_tags) for i in y]
    X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.1)
    model = Model(input, out)
    model.compile(optimizer="rmsprop", loss="categorical_crossentropy", 
    metrics=["accuracy"])
    model.fit(X_tr, np.array(y_tr), batch_size=32, epochs=5, 
    validation_split=0.1, verbose=1)
    model.save('my_model.h5')



    my_input="Albert Einstein is a great guy,he lives in berlin, Germany."
    print("--------------") 

    test_sentence = word_tokenize(my_input)
    x_test_sent = pad_sequences(sequences=[[word2idx.get(w, 0) for w in 
    test_sentence]],padding="post", value=0, maxlen=max_len)
    i = 0
    p = model.predict(np.array([x_test_sent[i]]))
    p = np.argmax(p, axis=-1)
    print("{:15}||{}".format("Word", "Prediction"))
    print(30 * "=")
    for w, pred in zip(test_sentence, p[0]):
    if w != 0:
         print("{:15}: {}".format(w, tags[pred]))
  • Please do not use the comment space for this kind of clarifications - edit & update your post instead – desertnaut Apr 03 '18 at 09:39
  • Try pickling your utility dictionaries, and when restarting the session and reconstructing them, load the previous session ones and compare them against one another. Most likely you get different indexing every new session which ruins your model's performance- unfortunately there's no way to test it without the data, however. – KonstantinosKokos Apr 03 '18 at 11:35

2 Answers2

1

please save your tags (tags = list(set(data["Tag"].values))) in pickle while generating your model.. This is will solve your problem.

There fore you need to save the following: 1.tags 2.model 3.word2idx

  • Can you explain the reason a bit. – Sourav Dalai Apr 04 '18 at 14:07
  • While you training your model, save the follwoings: – rajkumar subramanian Apr 05 '18 at 10:13
  • I had the same problem, I solved it by adding a `sorted` to any `list(set(` `sorted(list(set(long_data)))` which worked fine for characters. So when you train the model, your set is giving different order per session when you test and that is the problem. In this scenario, you should try saving the `list` as extreme measure if your data file changes – devssh Jul 14 '18 at 19:48
  • The reason for this problem is that your model expects "c", "a", "b" as the interpretation of the one-hot vector while training in the `set()` and when the session changes the set becomes "b", "a", "c" so it seems like it predicts randomly – devssh Jul 14 '18 at 19:55
0
import pandas as pd
import numpy as np
import os
from keras.preprocessing.sequence import pad_sequences
from keras.utils import to_categorical
from sklearn.model_selection import train_test_split
from keras.models import Model, Input,load_model
from keras.layers import LSTM, Embedding, Dense, TimeDistributed, Dropout,  
Bidirectional
from nltk import pos_tag, word_tokenize,sent_tokenize



data = pd.read_csv("E:\ml tut\entity recognition\exdataset.csv", 
encoding="latin1")
data = data.fillna(method="ffill")
words = list(set(data["Word"].values))
words.append("ENDPAD")
n_words = len(words); n_words

tags = list(set(data["Tag"].values))

save your tags in pickle or any other format

n_tags = len(tags); n_tags

class SentenceGetter(object):

    def __init__(self, data):
        self.n_sent = 1
        self.data = data
        self.empty = False
        agg_func = lambda s: [((w, p), t) for w, p, t in 
                 zip(s["Word"].values.tolist(),s["POS"].values.tolist(),     
                                             s["Tag"].values.tolist())]
        self.grouped = self.data.groupby("Sentence #").apply(agg_func)
        self.sentences = [s for s in self.grouped]

    def get_next(self):
        try:
            s = self.grouped["Sentence: {}".format(self.n_sent)]
            self.n_sent += 1
            return s
        except:
            return None

getter = SentenceGetter(data)

sent = getter.get_next()
print(sent)

sentences = getter.sentences

max_len = 50
word2idx = {w: i for i, w in enumerate(words)}

save your word2idx in pickle or any other format

tag2idx = {t: i for i, t in enumerate(tags)}





input = Input(shape=(max_len,))
model = Embedding(input_dim=n_words, output_dim=50, input_length=max_len) 
       (input)

model = Dropout(0.1)(model)

model = Bidirectional(LSTM(units=100, return_sequences=True, 
recurrent_dropout=0.1))(model)

out = TimeDistributed(Dense(n_tags, activation="softmax"))(model)  

if os.path.exists('my_model.h5'):
    print("loading model")
    model = load_model('my_model.h5')
else:
    print("training model")
    X = [[word2idx[w[0][0]] for w in s] for s in sentences]
    X = pad_sequences(maxlen=max_len, sequences=X, padding="post", 
    value=n_words - 1)
    y = [[tag2idx[w[1]] for w in s] for s in sentences]
    y = pad_sequences(maxlen=max_len, sequences=y, padding="post", 
    value=tag2idx["O"])
    y = [to_categorical(i, num_classes=n_tags) for i in y]
    X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.1)
    model = Model(input, out)
    model.compile(optimizer="rmsprop", loss="categorical_crossentropy", 
    metrics=["accuracy"])
    model.fit(X_tr, np.array(y_tr), batch_size=32, epochs=5, 
    validation_split=0.1, verbose=1)
    model.save('my_model.h5')



    my_input="Albert Einstein is a great guy,he lives in berlin, Germany."
    print("--------------") 

    test_sentence = word_tokenize(my_input)
    x_test_sent = pad_sequences(sequences=[[word2idx.get(w, 0) for w in 
    test_sentence]],padding="post", value=0, maxlen=max_len)
    i = 0
    p = model.predict(np.array([x_test_sent[i]]))
    p = np.argmax(p, axis=-1)
    print("{:15}||{}".format("Word", "Prediction"))
    print(30 * "=")
    for w, pred in zip(test_sentence, p[0]):
    if w != 0:
         print("{:15}: {}".format(w, tags[pred]))