我想在LSTM上稍微改变我的模型架构,因此它接受完全连接方法所做的相同的精确平坦输入。
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)
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:输入0与层lstm_17不兼容:预期ndim = 3,发现ndim = 2
如果我回去并且不压平x_train和y_train,它就可以了。但是,我希望这是“另一种模式选择”,它可以提供相同的预处理输入。我认为传递形状[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的序列,即(1, 748)
,它没有多大意义;或者您可以将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...