Как конвертировать 1D-сплющенный MNIST Keras в модель LSTM без отвинчивания? - PullRequest
0 голосов
/ 25 марта 2019

Я хочу немного изменить архитектуру моей модели в LSTM, чтобы она принимала те же точные сплюснутые входы, что и при полном подключении.

Рабочая модель Dnn из примеров Keras

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: Вход 0 несовместим со слоем lstm_17: ожидаемый ndim = 3,found ndim = 2

Если я вернусь и не сгладю x_train и y_train, это работает.Тем не менее, я бы хотел, чтобы это был «просто другой выбор модели», который использует тот же предварительно обработанный ввод.Я думал, что проходящая форма [1:] будет работать так, как будто это реальный сплющенный input_shape.Я уверен, что это что-то простое, что я упускаю из-за размерности, но я не мог получить это после часа отворота и отладки, хотя и не сообразил, что работы с 28x28 до 784 не сплющены, но я не понимаю, почемуработает.Большое спасибо!

Для бонусных баллов лучше всего подойдет пример того, как сделать DNN или LSTM в 1D (784) или 2D (28, 28).

1 Ответ

1 голос
/ 26 марта 2019

Слои RNN, такие как LSTM, предназначены для обработки последовательности (то есть серии векторов, для которых важен их порядок появления). Вы можете посмотреть на изображение сверху вниз и рассмотреть каждый ряд пикселей как вектор. Следовательно, изображение будет последовательностью векторов и может быть передано на уровень RNN. Следовательно, согласно этому описанию следует ожидать, что уровень RNN принимает входной сигнал формы (sequence_length, number_of_features). Вот почему, когда вы подаете изображения в сеть LSTM в их первоначальной форме, то есть (28,28), это работает.

Теперь, если вы настаиваете на подаче модели LSTM сглаженного изображения, то есть с формой (784,), у вас есть по крайней мере два варианта: либо вы можете рассматривать это как последовательность длины один, то есть (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...
...