Почему эти последовательная модель Keras и функциональный API действуют по-разному? - PullRequest
1 голос
/ 08 апреля 2020

У меня есть генератор, который выдает данные в форме (32, 9, 200, 1), где 32 - размер пакета. Модель для него выглядит следующим образом:

def create_model(le):
    optimizer = Adam(lr=0.001)

    model = Sequential()
    model.add(TimeDistributed(Conv1D(filters=32, kernel_size=30, activation='relu'), input_shape=(None, 200, 1)))

    model.add(TimeDistributed(BatchNormalization()))

    model.add(TimeDistributed(Conv1D(filters=32, kernel_size=10, activation='relu')))
    model.add(TimeDistributed(MaxPool1D(pool_size=2)))

    model.add(TimeDistributed(BatchNormalization()))

    model.add(TimeDistributed(Flatten()))

    model.add(LSTM(50))

    model.add(Dense(30, activation='relu'))
    model.add(Dense(len(le.classes_), activation='softmax'))

    model.compile(optimizer=optimizer, loss='sparse_categorical_crossentropy', metrics=['accuracy'])

    print(model.summary())

    return model

Эта модель хорошо работает. Вторым способом я получаю данные в форме 5x (32, 9, 200, 1). Причина 5x в том, что я выдаю список из 5 массивов для подачи модели с несколькими входами. Модель выглядит следующим образом:

def create_model():
    input_x = Input(batch_shape=(None, 200, 1), dtype='float32')

    conv_1 = TimeDistributed(Conv1D(64, kernel_size=(20), activation='relu'))(input_x)
    maxpool_1 = TimeDistributed(MaxPool1D(pool_size=(4)))(conv_1)
    bn_1 = TimeDistributed(BatchNormalization())(maxpool_1)

    conv_2 = TimeDistributed(Conv1D(64, kernel_size=(10), activation='relu'))(bn_1)
    maxpool_2 = TimeDistributed(MaxPool1D(pool_size=(4)))(conv_2)

    flatten = TimeDistributed(Flatten())(maxpool_2)

    lstm_1 = LSTM(50)(flatten)

    dense1 = Dense(units=64, activation='relu')(lstm_1)
    out = Dense(units=32, activation='relu')(dense1)
    model = Model(input_x, out)

    inputA = Input(shape=(latent_dimension, 1), dtype='float32')
    inputB = Input(shape=(latent_dimension, 1), dtype='float32')
    inputC = Input(shape=(latent_dimension, 1), dtype='float32')
    inputD = Input(shape=(latent_dimension, 1), dtype='float32')
    inputE = Input(shape=(latent_dimension, 1), dtype='float32')

    cnn_out1 = model(inputA)
    cnn_out2 = model(inputB)
    cnn_out3 = model(inputC)
    cnn_out4 = model(inputD)
    cnn_out5 = model(inputE)

    combined = concatenate([cnn_out1, cnn_out2, cnn_out3, cnn_out4, cnn_out5], axis=-1)

    fully_connected = Dense(64, activation="relu")(combined)
    outputs_fc = Dense(13, activation="softmax")(fully_connected)

    model_encoded = Model(
        inputs=[inputA, inputB, inputC, inputD, inputE], outputs=outputs_fc)

    adamtopimizer = optimizers.Adam(lr=0.001)

    model_encoded.compile(optimizer=adamtopimizer, loss='categorical_crossentropy', metrics=['accuracy'])

    print(model_encoded.summary())

    return model_encoded

Но вторая выдает ошибку, в строке conv_1:

ValueError: Входной тензор должен иметь ранг 3, 4 или 5, но было 2.

Эта ошибка возникает в create_model, так что это вообще до того, как генератор заработает, поэтому я не думаю, что это имеет отношение к генератору, который я использую.

Почему он хорошо работает в первом, но не работает во втором? Я могу дать любую информацию, которая вам нужна. Спасибо.

Edit-1: Если я изменю его на input_x = Input(batch_shape=(None, 9, 200, 1), dtype='float32'), он все равно выдаст ошибку выше.

1 Ответ

2 голосов
/ 08 апреля 2020

# Обновление от 4/14 Это то, что вы хотите?

from keras.layers import Input, Conv1D, TimeDistributed, LSTM, Concatenate, Dense, MaxPool1D, BatchNormalization, Flatten
from keras.models import Model

def create_model(input_shape=(9, 200, 1)):
    input_x = Input(shape=input_shape, dtype='float32')

    conv_1 = TimeDistributed(Conv1D(64, kernel_size=(20), activation='relu'))(input_x)
    maxpool_1 = TimeDistributed(MaxPool1D(pool_size=(4)))(conv_1)
    bn_1 = TimeDistributed(BatchNormalization())(maxpool_1)

    conv_2 = TimeDistributed(Conv1D(64, kernel_size=(10), activation='relu'))(bn_1)
    maxpool_2 = TimeDistributed(MaxPool1D(pool_size=(4)))(conv_2)

    flatten = TimeDistributed(Flatten())(maxpool_2)

    lstm_1 = LSTM(50)(flatten)

    dense1 = Dense(units=64, activation='relu')(lstm_1)
    out = Dense(units=32, activation='relu')(dense1)
    model = Model(input_x, out)

    inputA = Input(shape=input_shape, dtype='float32')
    inputB = Input(shape=input_shape, dtype='float32')
    inputC = Input(shape=input_shape, dtype='float32')
    inputD = Input(shape=input_shape, dtype='float32')
    inputE = Input(shape=input_shape, dtype='float32')

    cnn_out1 = model(inputA)
    cnn_out2 = model(inputB)
    cnn_out3 = model(inputC)
    cnn_out4 = model(inputD)
    cnn_out5 = model(inputE)

    combined = Concatenate(axis=-1)([cnn_out1, cnn_out2, cnn_out3, cnn_out4, cnn_out5])

    fully_connected = Dense(64, activation="relu")(combined)
    outputs_fc = Dense(13, activation="softmax")(fully_connected)

    model_encoded = Model(
        inputs=[inputA, inputB, inputC, inputD, inputE], outputs=outputs_fc)

    model_encoded.summary()
    return model


create_model()

------------ Старый ответ ниже

Вы неправильно указали batch_shape в Вход во вторую модель. Документ гласит:

batch_shape: Кортеж формы (целое число), включая размер пакета. Например, batch_shape = (10, 32) указывает, что ожидаемым вводом будут пакеты из 10 32-мерных векторов. (https://keras.io/layers/core/#input)

def create_model():
    input_x = Input(batch_shape=(32, 9, 200, 1), dtype='float32')

Кроме того, Ваша опубликованная первая модель имеет вход с произвольным размером пакета и (200, 1) размером тензора. См. Документацию:

Если вам когда-либо потребуется указать фиксированный размер пакета для ваших входных данных (это полезно для периодических сетей с сохранением состояния), вы можете передать аргумент batch_size слою. Если вы передадите оба слоя batch_size = 32 и input_shape = (6, 8), он будет ожидать, что каждая партия входных данных будет иметь форму пакета (32, 6, 8). (https://keras.io/getting-started/sequential-model-guide/#getting модель начала работы с кератами )

Вы можете изменить на

def create_model(le):
    optimizer = Adam(lr=0.001)

    model = Sequential()
    model.add(TimeDistributed(Conv1D(filters=32, kernel_size=30, activation='relu'), input_shape=(9, 200, 1), batch_size=32))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...