【问题标题】:Keras saved model predicting different values on different sessionKeras 保存的模型在不同的会话中预测不同的值
【发布时间】:2018-04-03 07:54:25
【问题描述】:

我已经训练了一个命名实体识别模型,在保存并加载它之后,它在同一个 IPython 会话中给出了正确的预测,但是每当我关闭会话并再次打开它时,加载的模型预测会随机。你能帮我解决这个问题吗?

我已经使用 hdf5 格式保存了模型:

Model.save("filename")

我正在使用以下方式加载它:

Model.load_model("filename")

这是我的完整代码

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]))

【问题讨论】:

  • 请不要使用评论空间进行此类澄清 - 改为编辑和更新您的帖子
  • 尝试腌制你的实用字典,并在重新启动会话并重建它们时,加载前一个会话并相互比较。很可能每个新会话都会得到不同的索引,这会破坏模型的性能——不幸的是,没有数据就无法测试它。

标签: machine-learning nlp keras


【解决方案1】:

请在生成模型时将标签 (tags = list(set(data["Tag"].values))) 保存在 pickle 中。这将解决您的问题。

因此,您需要保存以下内容: 1.标签 2.型号 3.word2idx

【讨论】:

  • 你能解释一下原因吗?
  • 训练模型时,请保存以下内容:
  • 我遇到了同样的问题,我通过将sorted 添加到任何list(set( sorted(list(set(long_data))) 来解决它,这对于字符来说效果很好。因此,当您训练模型时,您的集合在测试时会在每个会话中给出不同的顺序,这就是问题所在。在这种情况下,如果您的数据文件发生更改,您应该尝试将list 保存为极端度量
  • 这个问题的原因是你的模型在set()训练和会话改变时期望“c”、“a”、“b”作为one-hot向量的解释集合变成了“b”、“a”、“c”,所以看起来它是随机预测的
【解决方案2】:
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))

以 pickle 或任何其他格式保存您的标签

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)}

将 word2idx 保存为 pickle 或任何其他格式

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]))

【讨论】:

    猜你喜欢
    • 2019-07-11
    • 2018-06-30
    • 1970-01-01
    • 2020-08-01
    • 2021-02-08
    • 2019-09-04
    • 2019-01-24
    • 2017-11-25
    • 1970-01-01
    相关资源
    最近更新 更多