【问题标题】:How to use TF IDF vectorizer with LSTM in Keras Python如何在 Keras Python 中使用 TF IDF 矢量化器和 LSTM
【发布时间】:2026-02-01 22:25:16
【问题描述】:

我正在尝试在 Python 的 Keras 库中使用 LSTM 训练 Seq2Seq 模型。我想使用句子的 TF IDF 向量表示作为模型的输入并得到错误。

X = ["Good morning", "Sweet Dreams", "Stay Awake"]
Y = ["Good morning", "Sweet Dreams", "Stay Awake"]

vectorizer = TfidfVectorizer()
vectorizer.fit(X)
vectorizer.transform(X)
vectorizer.transform(Y)
tfidf_vector_X = vectorizer.transform(X).toarray() #shape - (3,6)
tfidf_vector_Y = vectorizer.transform(Y).toarray() #shape - (3,6)
tfidf_vector_X = tfidf_vector_X[:, :, None] #shape - (3,6,1) since LSTM cells expects ndims = 3
tfidf_vector_Y = tfidf_vector_Y[:, :, None] #shape - (3,6,1)

X_train, X_test, y_train, y_test = train_test_split(tfidf_vector_X, tfidf_vector_Y, test_size = 0.2, random_state = 1)
model = Sequential()
model.add(LSTM(output_dim = 6, input_shape = X_train.shape[1:], return_sequences = True, init = 'glorot_normal', inner_init = 'glorot_normal', activation = 'sigmoid'))
model.add(LSTM(output_dim = 6, input_shape = X_train.shape[1:], return_sequences = True, init = 'glorot_normal', inner_init = 'glorot_normal', activation = 'sigmoid'))
model.add(LSTM(output_dim = 6, input_shape = X_train.shape[1:], return_sequences = True, init = 'glorot_normal', inner_init = 'glorot_normal', activation = 'sigmoid'))
model.add(LSTM(output_dim = 6, input_shape = X_train.shape[1:], return_sequences = True, init = 'glorot_normal', inner_init = 'glorot_normal', activation = 'sigmoid'))
adam = optimizers.Adam(lr = 0.001, beta_1 = 0.9, beta_2 = 0.999, epsilon = None, decay = 0.0, amsgrad = False)
model.compile(loss = 'cosine_proximity', optimizer = adam, metrics = ['accuracy'])
model.fit(X_train, y_train, nb_epoch = 100)

以上代码抛出:

Error when checking target: expected lstm_4 to have shape (6, 6) but got array with shape (6, 1)

谁能告诉我出了什么问题以及如何解决?

【问题讨论】:

  • LSTM 将序列作为输入。您应该使用 word2vec 或 glove 中的词向量将句子从词序列转换为向量序列,然后将其传递给 LSTM。我不明白为什么以及如何将 tf-idf 与 LSTM 一起使用!

标签: python keras nlp lstm rnn


【解决方案1】:

目前,您在最后一层中返回维度 6 的序列。您可能希望返回一个维度为 1 的序列以匹配您的目标序列。我在这里不是 100% 确定,因为我没有使用 seq2seq 模型的经验,但至少代码以这种方式运行。不妨看看Keras blog 上的 seq2seq 教程。

除此之外,还有两个小点:使用 Sequential API 时,您只需为模型的第一层指定一个input_shape。此外,LSTM 层的 output_dim 参数已弃用,应替换为 units 参数:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split

X = ["Good morning", "Sweet Dreams", "Stay Awake"]
Y = ["Good morning", "Sweet Dreams", "Stay Awake"]

vectorizer = TfidfVectorizer().fit(X)

tfidf_vector_X = vectorizer.transform(X).toarray()  #//shape - (3,6)
tfidf_vector_Y = vectorizer.transform(Y).toarray() #//shape - (3,6)
tfidf_vector_X = tfidf_vector_X[:, :, None] #//shape - (3,6,1) 
tfidf_vector_Y = tfidf_vector_Y[:, :, None] #//shape - (3,6,1)

X_train, X_test, y_train, y_test = train_test_split(tfidf_vector_X, tfidf_vector_Y, test_size = 0.2, random_state = 1)

from keras import Sequential
from keras.layers import LSTM

model = Sequential()
model.add(LSTM(units=6, input_shape = X_train.shape[1:], return_sequences = True))
model.add(LSTM(units=6, return_sequences=True))
model.add(LSTM(units=6, return_sequences=True))
model.add(LSTM(units=1, return_sequences=True, name='output'))
model.compile(loss='cosine_proximity', optimizer='sgd', metrics = ['accuracy'])

print(model.summary())

model.fit(X_train, y_train, epochs=1, verbose=1)

【讨论】:

  • 感谢您的解决方案。但是该模型的拟合速度极慢,即使在数据集大小为 8000 的情况下也是如此。您能否就我如何以小批量运行它提出建议。
【解决方案2】:

如上图所示,网络期望最后一层作为输出层。您必须给出最终层的维度作为您的输出维度。

在您的情况下,它将是 行数 * 1,如错误所示 (6,1) 是您的维度。

在最后一层中将输出维度更改为 1

使用 keras,您可以设计自己的网络。因此您应该负责创建带有输出层的端到端隐藏层。

【讨论】: