Вопрос или проблема
Я новичок здесь и в глубоких обучения, поэтому заранее прошу прощения за неправильно форматированный код или формулировки. У меня есть набор данных, где я отслеживаю 4 переменные с 2 категориальными и 3 числовыми полями на 4 временных этапах.
Мне удалось построить фрейм данных следующим образом:
- cat1 – переменные с закодированными метками SckitLearn
- cat2 – временные этапы с закодированными метками SckitLearn
- num1 : num3 – нормализованные переменные SckitLearn
Я смог преобразовать это в список массивов numpy следующим образом:
Я хочу внедрить и объединить все эти поля перед подачей в LSTM в Keras, используя эту функцию:
def build_concat(df):
global inputs
inputs = []
global embeddings
embeddings = []
cat_cols = df.filter(like="cat")
num_cols = df.filter(like="num")
for cat_col in cat_cols:
cat_input = Input(shape=(4,4), name=cat_col)
unique_cat = cat_cols[cat_col].nunique()
embedding_size = min(np.ceil((unique_cat)/2), 20)
embedding_size = int(embedding_size)
cat_dim = unique_cat + 1
inputs.append(cat_input)
embeddings.append(Embedding(cat_dim, embedding_size, input_length = (4,4),
name=str(cat_col) + "_emb")(cat_input))
for num_col in num_cols:
num_input = Input(shape=(4,4), name=num_col)
inputs.append(num_input)
embeddings.append(num_input)
Но я получаю эту ошибку :
ValueError: Shape must be rank 3 but is rank 2 for ‘{{node so2_model/concat/concat}} = ConcatV2[N=5, T=DT_FLOAT, Tidx=DT_INT32](so2_model/cat1_emb/embedding_lookup/Identity_1, so2_model/cat2_emb/embedding_lookup/Identity_1, IteratorGetNext:2, IteratorGetNext:3, IteratorGetNext:4, so2_model/concat/concat/axis)’ with input shapes: [2,4,2], [2,4,2], [2,4], [2,4], [2,4], [].
Это мой список внедрений :
[<KerasTensor: shape=(None, 4, 4, 2) dtype=float32 (созданный слоем ‘cat1_emb’)>, <KerasTensor: shape=(None, 4, 4, 2) dtype=float32 (созданный слоем ‘cat2_emb’)>, <KerasTensor: shape=(None, 4, 4) dtype=float32 (созданный слоем ‘num1’)>, <KerasTensor: shape=(None, 4, 4) dtype=float32 (созданный слоем ‘num2’)>, <KerasTensor: shape=(None, 4, 4) dtype=float32 (созданный слоем ‘num3’)>]
Это мой список входных данных перед внедрением :
[<KerasTensor: shape=(None, 4, 4) dtype=float32 (созданный слоем ‘cat1’)>, <KerasTensor: shape=(None, 4, 4) dtype=float32 (созданный слоем ‘cat2’)>, <KerasTensor: shape=(None, 4, 4) dtype=float32 (созданный слоем ‘num1’)>, <KerasTensor: shape=(None, 4, 4) dtype=float32 (созданный слоем ‘num2’)>, <KerasTensor: shape=(None, 4, 4) dtype=float32 (созданный слоем ‘num3’)>]
Спасибо за вашу помощь!
Вам следует изменить форму ваших числовых слоев так, чтобы они имели форму (None,4,4,1)
. Для конкатенации вам нужно, чтобы все, кроме одной оси, были равны.
Если вы использовали:
tf.keras.layers.Reshape((4,4,1))(num_input)
это должно сработать.
Ответ или решение
При работе с набором данных, содержащим как категориальные, так и численные переменные, для использования в LSTM (Long Short-Term Memory) моделях часто возникают проблемы с конкатенацией этих переменных. Давайте подробно проанализируем основные трудности, которые могут возникнуть в этом контексте, а также предложим возможные решения.
Проблема конкатенации переменных
В вашем случае вы имеете дело с двумя категориальными переменными и тремя числовыми полями, за которыми вы следите в течение четырех временных диапазонов. Проблема, с которой вы столкнулись, связана с несовпадением форматов данных при попытке конкатенировать результирующие тензоры перед подачей их в модель LSTM.
Из сообщения об ошибке:
ValueError: Shape must be rank 3 but is rank 2 for '{{node so2_model/concat/concat}}...
выявляется, что проблема заключается в несоответствии размерностей тензоров. Чтобы конкатенировать тензоры, нужно, чтобы все, кроме одной оси (в данном случае это может быть ось временного компонента), имели одинаковую размерность.
Описание источников проблемы
-
Размерность тензоров:
- Ваша ошибка указывает на наличие тензоров с различными размерностями. Для категориальных переменных (после применения слоя Embedding) вы получаете тензоры размерности (None, 4, 4, 2), что служит корректным представлением для категориальных признаков. Но для числовых переменных у вас тензоры размерности (None, 4, 4), что не позволяет выполнить конкатенацию.
-
Форма для числовых данных:
- Как было правильно замечено, для числовых переменных необходимо изменить размерность с (None, 4, 4) на (None, 4, 4, 1). Это можно сделать с помощью слоя
Reshape
:tf.keras.layers.Reshape((4, 4, 1))(num_input)
. Это приведет к тому, что все входные данные будут иметь согласованную размерность для выполнения конкатенации.
- Как было правильно замечено, для числовых переменных необходимо изменить размерность с (None, 4, 4) на (None, 4, 4, 1). Это можно сделать с помощью слоя
Решение проблемы
Для того чтобы корректно конкатенировать ваши тензоры, рекомендуется внести следующие изменения в ваш код:
for num_col in num_cols:
num_input = Input(shape=(4, 4), name=num_col)
num_input_reshaped = tf.keras.layers.Reshape((4, 4, 1))(num_input) # Изменение размерности
inputs.append(num_input)
embeddings.append(num_input_reshaped)
Таким образом, после этих изменений все тензоры в embeddings
будут иметь размерности (None, 4, 4, X), что позволит вам выполнить конкатенацию без возникновения ошибок.
Заключение
Ключ к решению проблем с конкатенацией категориальных и числовых переменных для их дальнейшего использования в LSTM моделях заключается в согласовании размерностей тензоров. Убедитесь, что все тензоры имеют совместимую размерность, что позволяет избежать проблем, связанных с терминами и формами входных данных. С этими изменениями ваш код должен успешно выполнять конкатенацию и подготавливаться к дальнейшему обучению модели.
Надеюсь, эта информация была полезной для вас. Если у вас есть дополнительные вопросы или вам нужна дальнейшая помощь, не стесняйтесь обращаться!