Я построил модель LSTM в тензорном потоке, но она не предсказывает каких-либо полезных результатов. Мои данные, по сути, представляют собой последовательность кодов для нескольких идентификаторов, и я хочу, чтобы моя модель предсказывала следующий код в последовательности для каждого идентификатора (классификации).
Я структурировал свою модель так, чтобы она включала 5 последовательностей (ID, dx1, dx2, dx3), каждая из которых имеет один и тот же ID, а затем хочу, чтобы она выводила следующий dx1, dx2, dx3 в последовательности.
num_cats = 4 # number of categorical features
n_steps = 5 # number of timesteps in each sample
cat_size = [df['enrolid'].nunique(), df['dx1'].nunique(), df['dx2'].nunique(), df['dx3'].nunique()] # number of categories in each categorical feature
cat_embd_dim = [1191095, 100, 50, 20] # embedding dimension for each categorical feature
input_enrolid = Input(shape=(n_steps,), name='input_enrolid')
input_dx1 = Input(shape=(n_steps,), name='input_dx1')
input_dx2 = Input(shape=(n_steps,), name='input_dx2')
input_dx3 = Input(shape=(n_steps,), name='input_dx3')
embed_dx1 = Embedding(df['dx1'].nunique(), cat_embd_dim[1])(input_dx1)
embed_dx2 = Embedding(df['dx2'].nunique(), cat_embd_dim[2])(input_dx2)
embed_dx3 = Embedding(df['dx3'].nunique(), cat_embd_dim[3])(input_dx3)
lstm_dx1 = LSTM(32, input_shape=(n_steps, num_cats))(embed_dx1)
lstm_dx2 = LSTM(32, input_shape=(n_steps, num_cats))(embed_dx2)
lstm_dx3 = LSTM(32, input_shape=(n_steps, num_cats))(embed_dx3)
output_dx1 = Dense(1, activation='softmax')(lstm_dx1)
output_dx2 = Dense(1, activation='softmax')(lstm_dx2)
output_dx3 = Dense(1, activation='softmax')(lstm_dx3)
model = Model( [input_enrolid, input_dx1, input_dx2, input_dx3], [output_dx1, output_dx2, output_dx3])
Мой model.summary() выглядит следующим образом:
Model: "functional_15"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_dx1 (InputLayer) [(None, 5)] 0
__________________________________________________________________________________________________
input_dx2 (InputLayer) [(None, 5)] 0
__________________________________________________________________________________________________
input_dx3 (InputLayer) [(None, 5)] 0
__________________________________________________________________________________________________
embedding_39 (Embedding) (None, 5, 100) 154500 input_dx1[0][0]
__________________________________________________________________________________________________
embedding_40 (Embedding) (None, 5, 50) 79750 input_dx2[0][0]
__________________________________________________________________________________________________
embedding_41 (Embedding) (None, 5, 20) 28600 input_dx3[0][0]
__________________________________________________________________________________________________
lstm_51 (LSTM) (None, 32) 17024 embedding_39[0][0]
__________________________________________________________________________________________________
lstm_52 (LSTM) (None, 32) 10624 embedding_40[0][0]
__________________________________________________________________________________________________
lstm_53 (LSTM) (None, 32) 6784 embedding_41[0][0]
__________________________________________________________________________________________________
input_enrolid (InputLayer) [(None, 5)] 0
__________________________________________________________________________________________________
dense_21 (Dense) (None, 1) 33 lstm_51[0][0]
__________________________________________________________________________________________________
dense_22 (Dense) (None, 1) 33 lstm_52[0][0]
__________________________________________________________________________________________________
dense_23 (Dense) (None, 1) 33 lstm_53[0][0]
==================================================================================================
Total params: 297,381
Trainable params: 297,381
Non-trainable params: 0
Затем я компилирую и подгоняю свою модель:
model.compile(optimizer=Adam(lr=0.1), loss='categorical_crossentropy',metrics='accuracy' )
model.fit([ X_tr_cat1, X_tr_cat2, X_tr_cat3, X_tr_cat4], [y_train_dx1, y_train_dx2, y_train_dx3], epochs=3, batch_size = 1000)
Однако, подобрав мою модель, я вижу некоторые неточности и потери, которые не выглядят слишком обнадеживающими:
Epoch 1/3
1192/1192 [==============================] - 37s 31ms/step - loss: 0.0000e+00 - dense_21_loss: 0.0000e+00 - dense_22_loss: 0.0000e+00 - dense_23_loss: 0.0000e+00 - dense_21_accuracy: 0.0000e+00 - dense_22_accuracy: 8.3956e-07 - dense_23_accuracy: 8.3956e-07
Epoch 2/3
1192/1192 [==============================] - 37s 31ms/step - loss: 0.0000e+00 - dense_21_loss: 0.0000e+00 - dense_22_loss: 0.0000e+00 - dense_23_loss: 0.0000e+00 - dense_21_accuracy: 0.0000e+00 - dense_22_accuracy: 8.3956e-07 - dense_23_accuracy: 8.3956e-07
Epoch 3/3
1192/1192 [==============================] - 37s 31ms/step - loss: 0.0000e+00 - dense_21_loss: 0.0000e+00 - dense_22_loss: 0.0000e+00 - dense_23_loss: 0.0000e+00 - dense_21_accuracy: 0.0000e+00 - dense_22_accuracy: 8.3956e-07 - dense_23_accuracy: 8.3956e-07
Нет не только нулевых потерь на трех выходных сигналах и нулевой точности для первого плотного слоя, но и ни одно из значений не меняется в каждую эпоху!
Кроме того, когда я пытаюсь заставить модель предсказывать данные, которые я использовал для ее обучения, я получаю:
> y_prob=model.predict([ X_tr_cat1, X_tr_cat2, X_tr_cat3, X_tr_cat4])
> [array([[1.],
[1.],
[1.],
...,
[1.],
[1.],
[1.]], dtype=float32),
array([[1.],
[1.],
[1.],
...,
[1.],
[1.],
[1.]], dtype=float32),
array([[1.],
[1.],
[1.],
...,
[1.],
[1.],
[1.]], dtype=float32)]
При попытке увидеть фактические прогнозы для dx1:
> y_prob[0].argmax(axis=-1)
> array([0, 0, 0, ..., 0, 0, 0], dtype=int64)
Похоже, он предсказывает одно и то же предсказание 0 dx1 для каждой последовательности, где пустая строка '' была закодирована как 0 в моих данных.
Для дополнительного пояснения мой ввод X_tr_cat1 выглядит как
> X_tr_cat1
> array([[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0],
...,
[238218, 238218, 238218, 238218, 238218],
[238218, 238218, 238218, 238218, 238218],
[238218, 238218, 238218, 238218, 238218]])
и имеет форму (1191095, 5).
Хотя cat2, cat3, cat4 может содержать разные значения, форма и структура одинаковы - они просто относятся к кодам, в то время как cat1 относится к id: первый [0,0, 0, 0, 0] означает, что идентификатор был 0 для идентификатора 0 временами 1,2,3,4. , 5.
Мой вывод y_train_dx1 выглядит так:
array([[ 877],
[1313],
[1313],
...,
[ 0],
[ 0],
[ 0]])
и имеет форму (1191095, 1) - просто следующий код dx1 в последовательности для каждой входной последовательности.
Я действительно не знаю, что здесь не так с моей моделью - я думаю, что мои входные массивы отформатированы правильно? Но я не уверен, так как я новичок в TF.
Есть предложения, что исправить?
@Frightera Думаю, я просто пытаюсь найти наиболее вероятный прогноз для каждого из выходов dx1,dx2,dx3 вместе с их вероятностями. Стоит ли мне тогда использовать другую функцию активации? Я вижу, что sigmoid - это еще одна функция активации классификации, но она эквивалентна 2-элементному softmax, так что это тоже звучит неправильно?
Если бы я попытался использовать Dense(num_categories, activation = 'softmax') для получения вероятностей каждой категории в последнем слое, пришлось бы мне переформатировать мои данные y_train_dx1? Я получаю сообщение об ошибке "Фигуры несовместимы".






Dense(1, activation='softmax')у вас есть 1 единица, поэтому ваши прогнозы в форме(1,). Выводы Softmax будут суммировать до одного (1), с 1 единицей вы просто выводите вектор единиц (1 с) каждый раз. Также argmax с формой (1,) не имеет смысла.