Вопрос или проблема
Я работаю над моделью с несколькими входами и выходами. Передача выходов в model.fit в виде словаря работает хорошо, но если я хочу сделать то же самое с входами, я всегда получаю следующую ошибку:
Недопустимая форма ввода для входного тензора("data_1:0", форма=(None, 48, 2), dtype=float32). Ожидаемая форма (None, 1), но вход имеет несовместимую форму (None, 48, 2)
Аргументы, полученные от Functional.call():
• inputs={'Linear_inputs': 'tf.Tensor(shape=(None, 1), dtype=float32)', 'LSTM_inputs': 'tf.Tensor(shape=(None, 48, 2), dtype=float32)'}
• training=True
• mask={'Linear_inputs': 'None', 'LSTM_inputs': 'None'}
Процесс завершился с кодом 1
Мой код для построения и обучения:
#входные слои
Linear_inputs = tf.keras.layers.Input(shape=(1,), name="Linear_inputs")
LSTM_inputs = tf.keras.layers.Input(shape=(step_size, 2), name="LSTM_inputs")
#общий путь
#x = tf.keras.layers.LSTM(50, activation='tanh', return_sequences=True)(inputs)
#x = tf.keras.layers.Dropout(0.1)(x)
#x = tf.keras.layers.Dense(100, activation='relu')(inputs)
#x = tf.keras.layers.Dropout(0.1)(x)
#ветка скорости ротора
rpm = tf.keras.layers.Dense(4, activation='tanh', kernel_regularizer="l1l2", kernel_initializer="he_uniform")(Linear_inputs)
Y_rpm = tf.keras.layers.Dense(1, activation='sigmoid', name="Y_rpm", kernel_regularizer="l1l2", kernel_initializer="he_uniform")(rpm)
#ветка активной мощности
kW = tf.keras.layers.LSTM(40, activation='tanh', kernel_regularizer="l2", kernel_initializer="RandomNormal")(LSTM_inputs)
kW = tf.keras.layers.Dropout(0.1)(kW)
kW = tf.keras.layers.Dense(30, activation='tanh')(kW)
kW = tf.keras.layers.Dropout(0.1)(kW)
Y_kW = tf.keras.layers.Dense(1, activation='sigmoid', name="Y_1_C")(kW)
#ветка температуры переднего подшипника
f_C = tf.keras.layers.LSTM(40, activation='tanh', kernel_regularizer="l2", kernel_initializer="RandomNormal")(LSTM_inputs)
f_C = tf.keras.layers.Dropout(0.1)(f_C)
f_C = tf.keras.layers.Dense(30, activation='tanh')(f_C)
f_C = tf.keras.layers.Dropout(0.1)(f_C)
Y_f_C = tf.keras.layers.Dense(1, activation='sigmoid', name="Y_2_C")(f_C)
#ветка температуры заднего подшипника
r_C = tf.keras.layers.LSTM(40, activation='tanh', kernel_regularizer="l2", kernel_initializer="RandomNormal")(LSTM_inputs)
r_C = tf.keras.layers.Dropout(0.1)(r_C)
r_C = tf.keras.layers.Dense(30, activation='tanh')(r_C)
r_C = tf.keras.layers.Dropout(0.1)(r_C)
Y_r_C = tf.keras.layers.Dense(1, activation='sigmoid', name="Y_O_C")(r_C)
#создание модели и оптимизатора
gearing_model = tf.keras.Model(inputs=[Linear_inputs, LSTM_inputs], outputs=[Y_rpm, Y_kW, Y_f_C, Y_r_C])
optimizer = Adam(learning_rate=0.0001)
#optimizer = Adam(learning_rate=0.00001)
#определение потерь
losses = {"Y_rpm": "mse", "Y_1_C": "mse", "Y_2_C": "mse", "Y_O_C": "mse"}
lossWeights = {"Y_rpm": 1.0, "Y_1_C": 1.0, "Y_2_C": 1.0, "Y_O_C": 1.0}
#компиляция модели
gearing_model.compile(optimizer=optimizer, loss=losses, loss_weights=lossWeights, metrics=["mse", "mse", "mse", "mse"])
reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor="loss", factor=0.5, patience=3)
print(gearing_model.summary())
print(X_train_1_lin.shape)
print(X_train_1_lstm.shape)
history0 = gearing_model.fit({"Linear_inputs": X_train_1_lin, "LSTM_inputs": X_train_1_lstm},
{"Y_rpm": Y_train_1_lin, "Y_1_C": Y_train_1_lstm[:, 0], "Y_2_C": Y_train_1_lstm[:, 1], "Y_O_C": Y_train_1_lstm[:, 2]},
epochs=30, batch_size=128, callbacks=reduce_lr, shuffle=False)
history1 = gearing_model.fit([X_train_2_lin, X_train_2_lstm],
{"Y_rpm": Y_train_2_lin, "Y_1_C": Y_train_2_lstm[:, 0], "Y_2_C": Y_train_2_lstm[:, 1], "Y_O_C": Y_train_2_lstm[:, 2]},
epochs=30, batch_size=128, callbacks=reduce_lr, shuffle=False)
history2 = gearing_model.fit([X_train_3_lin, X_train_3_lstm],
{"Y_rpm": Y_train_3_lin, "Y_1_C": Y_train_3_lstm[:, 0], "Y_2_C": Y_train_3_lstm[:, 1], "Y_O_C": Y_train_3_lstm[:, 2]},
epochs=30, batch_size=128, callbacks=reduce_lr, shuffle=False)
Я использую Python 3.12 и Keras 3.4.0.
Передача входов, как это сделано в history1 и history2, работает, но словарь в history0 не работает. У меня нет проблем с выходами. Если я поменяю X_train_1_lin на X_train_1_lstm, это сработает – но я не могу найти причину. Любые предложения приветствуются!
Попробуйте определить ваши входы модели как словарь:
tf.keras.Model(inputs={"Linear_inputs":Linear_inputs, "LSTM_inputs":LSTM_inputs], outputs=[Y_rpm, Y_kW, Y_f_C, Y_r_C])
Ответ или решение
Решение проблемы с несколькими входами в Keras при использовании словаря в model.fit
При работе с нейронными сетями в Keras, особенно при использовании нескольких входов и выходов, важно правильно передавать данные в модель. В данном случае возникла ошибка при попытке передать входные данные в формате словаря во время обучения модели. Рассмотрим детали проблемы и пути её решения.
Описание проблемы
Вы столкнулись с ошибкой, связанной с несовпадением форматов входных данных:
Invalid input shape for input Tensor("data_1:0", shape=(None, 48, 2), dtype=float32). Expected shape (None, 1), but input has incompatible shape (None, 48, 2)
Это сообщение указывает на то, что первый вход вашей модели ожидает данные с формой (None, 1)
, тогда как по факту передается массив с формой (None, 48, 2)
для другого входа, что, в свою очередь, приводит к несовпадению.
Причины ошибки
-
Структура ввода: Когда вы вызываете
gearing_model.fit()
, Keras ожидает, что входные данные будут переданы в соответствии с определенной структурой. Когда вы передаете данные в виде словаря, важно, чтобы ключи словаря соответствовали именам входов, определенным при создании модели. -
Неправильная или неполная передача данных: Поскольку код работает в случае вызова
model.fit()
с массивами, но не со словарем, проблема может заключаться в несоответствии между названиями входов и фактическими массивами данных.
Решение проблемы
-
Определите входные данные в словаре: Попробуйте инициализировать модель, используя словарь для входных данных. Это обеспечивает более явную связь между именами входов и самими данными.
Пример:
inputs = { "Linear_inputs": Linear_inputs, "LSTM_inputs": LSTM_inputs } gearing_model = tf.keras.Model(inputs=inputs, outputs=[Y_rpm, Y_kW, Y_f_C, Y_r_C])
-
Проверка данных: Убедитесь, что массивы, передаваемые в
model.fit()
, имеют соответствующие размеры. Например:print("Форма линейных данных:", X_train_1_lin.shape) # Должно быть (num_samples, 1) print("Форма LSTM данных:", X_train_1_lstm.shape) # Должно быть (num_samples, 48, 2)
-
Использование отметки имен входов: При вызове
fit
, передавайте данные как словарь, где ключи соответствуют именам входов:history0 = gearing_model.fit( {"Linear_inputs": X_train_1_lin, "LSTM_inputs": X_train_1_lstm}, { "Y_rpm": Y_train_1_lin, "Y_1_C": Y_train_1_lstm[:, 0], "Y_2_C": Y_train_1_lstm[:, 1], "Y_O_C": Y_train_1_lstm[:, 2] }, epochs=30, batch_size=128, callbacks=reduce_lr, shuffle=False )
Заключение
Использование модели с несколькими входами требует четкого определения форматов входных и выходных данных. Применяя подход с использованием словаря при передаче данных, вы можете облегчить процесс и избежать несовпадений. Внимательно проверяйте размеры и названия ваших массивов данных. Это поможет вам успешно обучить вашу модель без ошибок.