【问题标题】:Keras LSTM model giving different predictions on same input when size of input has changed?当输入大小发生变化时,Keras LSTM 模型对相同输入给出不同的预测?
【发布时间】:2019-07-27 08:58:12
【问题描述】:

我正在使用 Keras 构建一个用于文本分类的 LSTM,并且正在玩弄不同的输入句子以了解正在发生的事情,但我得到了奇怪的输出。例如:

句子 1 = “周二,51 岁的 [Mary] Barra 女士完成了一段非凡的个人旅程,她被任命为通用汽车的下一任首席执行官,并且是第一位在一家专业公司担任最高职位的女性汽车公司。”

句子 2 = “周二,51 岁的 [Mary] Barra 女士被任命为通用汽车的下一任首席执行官,也是第一位在一家大型汽车公司担任最高职位的女性。”

模型预测类“目标”(0),当句子 2 是输入数组中的唯一元素时输出 0.4242。它预测“主观”(1),句子 1 的输出为 0.9061。如果它们都(作为单独的字符串)作为同一数组中的输入,则两者都被归类为“主观”(1) - 但句子 1 输出 0.8689 和 2输出 0.5607。似乎它们正在影响彼此的输出。每个句子在输入数组中的哪个索引都没有关系。

代码如下:

max_length = 500

from keras.preprocessing.sequence import pad_sequences
from keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer(num_words=5000, lower=True,split=' ')
tokenizer.fit_on_texts(dataset["sentence"].values)
#print(tokenizer.word_index)  # To see the dicstionary
X = tokenizer.texts_to_sequences(dataset["sentence"].values)
X = pad_sequences(X, maxlen=max_length)

y = np.array(dataset["label"])

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=0)

import numpy
from keras.datasets import imdb
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers.embeddings import Embedding
from keras.preprocessing import sequence
# fix random seed for reproducibility
numpy.random.seed(7)


X_train = sequence.pad_sequences(X_train, maxlen=max_length)
X_test = sequence.pad_sequences(X_test, maxlen=max_length)
embedding_vector_length = 32

###LSTM
from keras.layers.convolutional import Conv1D
from keras.layers.convolutional import MaxPooling1D
model = Sequential()
model.add(Embedding(5000, embedding_vector_length, input_length=max_length))
model.add(Conv1D(filters=32, kernel_size=3, padding='same', activation='sigmoid'))
model.add(MaxPooling1D(pool_size=2))
model.add(LSTM(100))
model.add(Dense(1, activation='sigmoid'))
from keras import optimizers
sgd = optimizers.SGD(lr=0.9)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])
print(model.summary())

model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=3, batch_size=64)

# save model
model.save('LSTM.h5')

然后我在一个单独的脚本中重新加载了模型,并给它输入了硬编码的句子:

model = load_model('LSTM.h5')

max_length = 500

from keras.preprocessing.sequence import pad_sequences
from keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer(num_words=5000, lower=True,split=' ')
tokenizer.fit_on_texts(article_sentences)
#print(tokenizer.word_index)  # To see the dicstionary
X = tokenizer.texts_to_sequences(article_sentences)
X = pad_sequences(X, maxlen=max_length)

prediction = model.predict(X)
print(prediction)
for i in range(len(X)):
    print('%s\nLabel:%d' % (article_sentences[i], prediction[i]))

我在训练模型之前和在加载模型的脚本中设置了随机种子,在加载模型时我是否遗漏了什么?我应该以不同的方式排列我的数据吗?

【问题讨论】:

  • 您找到答案了吗?我最近一直在努力解决这个问题

标签: python machine-learning keras nlp lstm


【解决方案1】:

在预测的时候,你总是要把tokenizer和预测文本匹配起来,所以打印出X,也许你会发现两次预测之间的区别。

预测中的tokenizer 应该与训练中的 tokenizer 相同。但是在您的代码中,您将 tokenizer 与预测文本相匹配。

【讨论】:

  • 问题可能出在标记化字典上(因为它会因多个示例而更大/不同)?我假设这会改变输出,因为它改变了特性。我需要将字典标准化为模型训练的字典吗?
  • 这只是我的猜测,因为两次预测的差距很小,同时两次预测的特征之间的差异应该很小。把字典规范成一本,你可以试试。你知道如何保存Tokenizer 模型吗?更常见的是,我们会在训练后保存Tokenizer,并在预测时加载Tokenizer
【解决方案2】:

您正在拟合一个新的 tokenizer,它与您的模型所训练的 tokenzier 不同。因此,为此您需要做的第一件事是pickle tokenizer,而预测不适合 tokenizer 再次使用该 pickle 分词器 您可以直接将该标记器用作X = tokenizer.texts_to_sequences(article_sentences) 无需再次适合。希望对你有帮助!

【讨论】:

    猜你喜欢
    • 2023-03-28
    • 2021-01-25
    • 2018-09-13
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 1970-01-01
    相关资源
    最近更新 更多