Ошибка LSTM — «логиты и метки должны иметь одинаковую форму»

#tensorflow #lstm

#tensorflow #lstm

Вопрос:

Я искал другие темы здесь относительно ошибки, но не могу разобраться в проблеме. Я пытаюсь создать LSTM, используя игрушечный набор данных с двумя предикторами и тремя результатами, установив для выходного слоя значение sigmoid таким образом, чтобы каждая метка результата имела вероятность между 0-1. Мой код:

 import pandas as pd
import numpy as np
import tensorflow as tf

#create toy dataset
d = {'custID': [101,101,101,102,102,102,103,103,103],
     'X1': [1,1,1,0,0,0,1,1,0],
     'X2': [0,1,0,1,1,1,1,1,0],
     'y1': [0,0,1,0,1,1,0,0,1],
     'y2': [0,1,1,0,0,1,1,0,1],
     'y3':[0,0,0,0,0,1,0,1,0]}

data = pd.DataFrame(data=d)

#seperate preds (X) from outcome (y)
X = data[['custID','X1','X2']]
y = data[['custID','y1','y2','y3']]

X.set_index('custID', inplace=True)
y.set_index('custID', inplace=True)

#reshape
X = X.values.reshape(3,3,2)
print(X)

y = y.values.reshape(3,3,3)
print(y)

#create LSTM
model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(6, input_shape=(3,2)),
    tf.keras.layers.LSTM(12, return_sequences = False),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(3, activation='sigmoid')
])

model.compile(optimizer=tf.keras.optimizers.Adam(),loss='binary_crossentropy')
model.fit(X,y, epochs=10)
 

Это приводит к ошибке (* Ошибка значения: логиты и метки должны иметь одинаковую форму ((Нет, 3) против (Нет, 3, 3))). Это работает, если я устанавливаю для активации выходного слоя значение softmax, но это дает вероятность для всех 3 меток, сумма которых равна 1, вместо вероятности для каждой метки.

Ответ №1:

Исправление проблемы «одинаковой формы»

Я думаю, вы хотите изменить свою модель на это

 #create LSTM
model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(6, input_shape=(3,2)),
    tf.keras.layers.LSTM(12, return_sequences=True),
    tf.keras.layers.Dense(3, activation='sigmoid')
])
 

и если мы посмотрим на сводку модели

 model.summary()
 

Мы получаем следующий вывод

 Layer (type)                 Output Shape              Param #   
=================================================================
dense_16 (Dense)             (None, 3, 6)              18        
_________________________________________________________________
lstm_8 (LSTM)                (None, 3, 12)             912       
_________________________________________________________________
dense_17 (Dense)             (None, 3, 3)              39        
=================================================================
Total params: 969
Trainable params: 969
Non-trainable params: 0
 

Мы видим, что действительно похоже, что данные передаются в правильной форме

Показывая, что эта модель работает

Давайте возьмем приведенную выше модель и обучим ее

 model.compile(optimizer=tf.keras.optimizers.Adam(),loss='binary_crossentropy')
dataSet = tf.data.Dataset.from_tensors((X,y)).repeat(1000)
model.fit(dataSet, epochs=5)
 

Возвращает следующие результаты обучения

 Epoch 1/5
1000/1000 [==============================] - 2s 2ms/step - loss: 0.2522
Epoch 2/5
1000/1000 [==============================] - 2s 2ms/step - loss: 0.0142
Epoch 3/5
1000/1000 [==============================] - 2s 2ms/step - loss: 0.0048
Epoch 4/5
1000/1000 [==============================] - 2s 2ms/step - loss: 0.0023
Epoch 5/5
1000/1000 [==============================] - 2s 2ms/step - loss: 0.0012
 

Похоже, он тренируется фантастически!

Я думаю, что основной проблемой было то return_sequence=False , что в основном избавлялось от вашего второго измерения данных. В Flatten этом не было необходимости, и если вы исправили return_sequence, то сглаживание вызвало другую проблему.

Дайте мне знать, если это решит вашу проблему

Комментарии:

1. Отлично, спасибо. Не могли бы вы объяснить, что делает эта строка: DataSet = tf.data. Dataset.from_tensors((X,y)).повторить (1000)?

2. эта строка принимает обучающие данные x, y и повторяет их 1000 раз. Теперь каждая эпоха действительно представляет собой многократный просмотр данных, но довольно неприятно видеть, что на выходе отображается 5000 эпох, так что это просто делает то же самое, но только с 5 строками. Если это отвечает на ваш вопрос, пожалуйста, отметьте его как принятый ответ в соответствии со стандартной практикой SO.