如何在不展平的情况下将 1D 展平 MNIST Keras 转换为 LSTM 模型?

How to convert 1D flattened MNIST Keras to LSTM model without unflattening?

我想在 LSTM 上稍微更改我的模型架构,以便它接受完全连接方法所接受的完全相同的扁平化输入。

来自 Keras 示例的工作 Dnn 模型

import keras

from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.utils import to_categorical

# import the data
from keras.datasets import mnist

# read the data
(x_train, y_train), (x_test, y_test) = mnist.load_data()

num_pixels = x_train.shape[1] * x_train.shape[2] # find size of one-dimensional vector

x_train = x_train.reshape(x_train.shape[0], num_pixels).astype('float32') # flatten training images
x_test = x_test.reshape(x_test.shape[0], num_pixels).astype('float32') # flatten test images

# normalize inputs from 0-255 to 0-1
x_train = x_train / 255
x_test = x_test / 255

# one hot encode outputs
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

num_classes = y_test.shape[1]
print(num_classes)



# define classification model
def classification_model():
    # create model
    model = Sequential()
    model.add(Dense(num_pixels, activation='relu', input_shape=(num_pixels,)))
    model.add(Dense(100, activation='relu'))
    model.add(Dense(num_classes, activation='softmax'))


    # compile model
    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
    return model


# build the model
model = classification_model()

# fit the model
model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10, verbose=2)

# evaluate the model
scores = model.evaluate(x_test, y_test, verbose=0)

同样的问题,但尝试使用 LSTM(仍然存在语法错误)

def kaggle_LSTM_model():
    model = Sequential()
    model.add(LSTM(128, input_shape=(x_train.shape[1:]), activation='relu', return_sequences=True))
    # What does return_sequences=True do?
    model.add(Dropout(0.2))

    model.add(Dense(32, activation='relu'))
    model.add(Dropout(0.2))

    model.add(Dense(10, activation='softmax'))

    opt = tf.keras.optimizers.Adam(lr=1e-3, decay=1e-5)
    model.compile(loss='sparse_categorical_crossentropy', optimizer=opt,
             metrics=['accuracy'])

    return model

model_kaggle_LSTM = kaggle_LSTM_model()

# fit the model
model_kaggle_LSTM.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10, verbose=2)

# evaluate the model
scores = model_kaggle_LSTM.evaluate(x_test, y_test, verbose=0)

问题在这里:

model.add(LSTM(128, input_shape=(x_train.shape[1:]), activation='relu', return_sequences=True))

ValueError: Input 0 is incompatible with layer lstm_17: expected ndim=3, found ndim=2

如果我返回并且不展平 x_train 和 y_train,它会起作用。但是,我希望它是 "just another model choice" 来提供相同的预处理输入。我认为传递 shape[1:] 会起作用,因为它是真正的扁平 input_shape。我确定我很容易遗漏维度,但经过一个小时的调试和调试后我无法得到它,虽然确实弄清楚了没有将 28x28 展平为 784 作品,但我不明白为什么会这样作品。非常感谢!

对于奖励积分,最好是一个如何在 1D (784,) 或 2D (28, 28) 中执行 DNN 或 LSTM 的示例。

诸如 LSTM 之类的 RNN 层用于序列处理(即一系列向量,它们的出现顺序很重要)。您可以从上到下查看图像,并将每一行像素视为一个向量。因此,图像将是一个向量序列,可以被馈送到 RNN 层。因此,根据此描述,您应该期望 RNN 层采用 (sequence_length, number_of_features) 形状的输入。这就是为什么当您将图像以其原始形状(即 (28,28) 提供给 LSTM 网络时,它起作用了。

现在,如果您坚持为 LSTM 模型提供扁平图像,即形状 (784,),您至少有两个选择:要么您可以将其视为长度为 1 的序列,即 [=14] =],意义不大;或者您可以向模型添加一个 Reshape 层,以将输入重塑为适合 LSTM 层输入形状的原始形状,如下所示:

from keras.layers import Reshape

def kaggle_LSTM_model():
    model = Sequential()
    model.add(Reshape((28,28), input_shape=x_train.shape[1:]))
    # the rest is the same...