首页 > 解决方案 > Keras 功能 API 从带有 LSTM 层的 Keras Sequential API 产生不同的结果

问题描述

我正在比较使用 Keras 的顺序和功能 API 构建的模型,并发现某些类型的模型会产生非常不同的结果。

我正在为我的模型使用 IMDB 数据集。

如果我创建一个只有EmbeddingDense层的模型,结果非常相似。

这是一个例子:

# imports
from tensorflow.keras.layers import Dense, LSTM, Flatten, Embedding
from tensorflow.keras import Input, Model
from tensorflow.keras.models import Sequential
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.layers.experimental.preprocessing import TextVectorization
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

顺序 API 的代码:

df = pd.read_csv('url_for_imdb_csv_file_here')
df['sentiment'].replace(['positive', 'negative'], [1, 0], inplace=True)
X_train, X_test, y_train, y_test = train_test_split(df['review'], df['sentiment'], test_size=0.2, random_state=1985)
tokenizer = Tokenizer(num_words=10000)
tokenizer.fit_on_texts(X_train)
train_seq = tokenizer.texts_to_sequences(X_train)
test_seq  = tokenizer.texts_to_sequences(X_test)
train_seq = pad_sequences(train_seq, maxlen=250)
test_seq  = pad_sequences(test_seq, maxlen=250)
mod = Sequential([
    Embedding(10000, 25, input_length=250),
    Flatten(),
    Dense(25, activation='relu'),
    Dense(25, activation='relu'),
    Dense(1, activation  = 'sigmoid')
])
mod.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
mod.fit(train_seq, y_train.values, validation_split=0.2, epochs=2)

这在两个时期后产生了约 88% 的准确度。

如果我使用功能 API 重新创建相同的模型,我将得到相同的结果。代码如下。

使用顺序 API 的代码

vectorizer = TextVectorization(max_tokens=10000, output_sequence_length=250)
vectorizer.adapt(X_train.values)
text_input = Input(shape=(1,), dtype='string')
x = vectorizer(text_input)
x = Embedding(10000, 25, input_length=250)(x)
x = Flatten()(x)
x = Dense(25, activation='relu')(x)
x = Dense(25, activation='relu')(x)
output = Dense(1, activation='sigmoid')(x)
mod1 = Model(text_input, output)
mod1.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
mod1.fit(X_train.values, y_train.values, validation_split=0.2, epochs=5)

这给了我大约相同的结果。

到目前为止,一切都很好。

但是,当我尝试添加 LSTM 层时,结果明显不同。

这是我正在使用的两个示例。我Dense用一层换掉LSTM一层并保持其他一切不变。

新的顺序 API 代码:

mod = Sequential([
    Embedding(10000, 25, input_length=250),
    LSTM(25),
    Dense(25, activation='relu'),
    Dense(1, activation  = 'sigmoid')
])
mod.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
mod.fit(train_seq, y_train.values, validation_split=0.2, epochs=2)

这给出了与以前的模型大致相同的结果。

但是,当我使用功能 API 重新创建此版本时,准确率在第 2 轮达到 64% 左右的峰值,然后又回落到约 50%。

新功能 API:

vectorizer = TextVectorization(max_tokens=10000, output_sequence_length=250)
vectorizer.adapt(X_train.values)
text_input = Input(shape=(1,), dtype='string')
x = vectorizer(text_input)
x = Embedding(10000, 25, input_length=250)(x)
x = LSTM(25)(x)
x = Dense(25, activation='relu')(x)
output = Dense(1, activation='sigmoid')(x)
mod1 = Model(text_input, output)

这不会产生相同的结果,即使它在我看来与Sequential示例相同。

有没有我遗漏的东西不能使两者相同,或者这是功能 API 工作方式的特殊性?

谢谢你。

标签: pythontensorflowkerastensorflow2.0

解决方案


推荐阅读