Вопрос или проблема
Я создаю теггер частей речи для нашего языка. Я передаю токены слова и теги, используя Tokenizer(). Функции для слова и тега разные.
# кодировать Y
tag_tokenizer = Tokenizer()
tag_tokenizer.fit_on_texts(tags)
Y_encoded = tag_tokenizer.texts_to_sequences(tags)
У меня есть простая двунаправленная LSTM для предсказания алгоритма.
bidirect_model = Sequential()
bidirect_model.add(Embedding(input_dim = VOCABULARY_SIZE,
output_dim = EMBEDDING_SIZE,
input_length = MAX_SEQ_LENGTH,
trainable = False
))
bidirect_model.add(Bidirectional(LSTM(64, return_sequences=True)))
bidirect_model.add(TimeDistributed(Dense(NUM_CLASSES, activation='softmax')))
bidirect_model.compile(loss="categorical_crossentropy",
optimizer="adam",
metrics=['acc'])
bidirect_training = bidirect_model.fit(Xtrain, ytrain, batch_size=128, epochs=10, validation_data=(Xvalidation, yvalidation))
loss, accuracy = bidirect_model.evaluate(Xtest, ytest, verbose = 1)
print("Потери: {0},\nТочность: {1}".format(loss, accuracy*100))
Результат довольно хорош, точность больше 94%. Но когда дело доходит до фактического преобразования вывода из токенов в слова, это немного затруднительно.
tag_tokenizer.sequences_to_texts(ytest.argmax(2))
Когда я пытаюсь преобразовать ytest в текст, это работает нормально, но когда я использую тот же метод с предсказанием, это не преобразует его правильно.
ypred = bidirect_model.predict(Xtest)
tag_tokenizer.sequences_to_texts(ypred.argmax(2))
это возвращает правильное количество тегов, но может вернуть только одно название тега для всех них. (Например, существительное для каждого тега, но должны быть и другие теги частей речи). Я заметил, что когда я предсказываю с помощью LSTM, данные фактически меняются в другой формат:
Это ypred:
array([[[9.96039510e-01, 3.83606239e-05, 3.69549962e-05, ...,
5.24025600e-05, 9.90346816e-05, 4.23052406e-04],
[9.97439384e-01, 3.10516843e-05, 2.83600530e-05, ...,
3.12017110e-05, 5.57345738e-05, 2.51515419e-04],
[9.98397648e-01, 2.60055913e-05, 2.21154296e-05, ...,
1.76890717e-05, 2.89566851e-05, 1.39188676e-04],
...,
[1.67124510e-01, 2.64671326e-01, 1.25262424e-01, ...,
4.61455435e-03, 3.27696186e-03, 2.74900091e-03],
[1.39361277e-01, 2.67008126e-01, 1.36608765e-01, ...,
4.63735918e-03, 3.30406637e-03, 2.69036856e-03],
Но на самом деле мой ytest является:
array([[[1., 0., 0., ..., 0., 0., 0.],
[1., 0., 0., ..., 0., 0., 0.],
[1., 0., 0., ..., 0., 0., 0.],
...,
[0., 1., 0., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.],
[0., 0., 1., ..., 0., 0., 0.]],
[[1., 0., 0., ..., 0., 0., 0.],
[1., 0., 0., ..., 0., 0., 0.],
[1., 0., 0., ..., 0., 0., 0.],
Я попробовал округлить числа, но это тоже не сработало.
Кажется, что ypred
— это вероятность, а ytest
— это кодировка one-hot. Наиболее распространенный способ преобразования вероятности в одно предсказание категории — это softmax.
Ответ или решение
Чтобы преобразовать предсказания вашей модели в текст после выполнения предсказаний с использованием рекуррентной нейронной сети (RNN), необходимо учесть несколько аспектов, связанных с форматом выходных данных. Ваша задача заключается в том, чтобы правильно интерпретировать вероятностные предсказания и сопоставить их с тегами частей речи (PoS).
1. Понимание формата выходных данных
После выполнения предсказаний с использованием модели, вы получаете массив ypred
, который содержит вероятности для каждого класса (тега) на каждом шаге (слове). Например, для каждой входной последовательности длины T
и количества классов C
, вы получаете массив размерности (количество примеров, T, C)
.
С другой стороны, ytest
в вашем коде представляет собой одномерную бинарную матрицу (one-hot encoded), где на каждом шаге указано, к какому тегу относится слово.
2. Преобразование предсказаний в текст
Для того чтобы преобразовать вероятностные предсказания в текст, вам нужно выполнить следующие шаги:
2.1 Применение операции argmax
Чтобы извлечь наиболее вероятный тег для каждого слова из предсказаний ypred
, необходимо применить функцию argmax
вдоль второй оси:
# Получение индексов предсказанных тегов
predicted_indices = ypred.argmax(axis=-1) # форма (количество примеров, T)
2.2 Преобразование индексов в текст
Теперь, когда у вас есть индексы предсказанных тегов, вы можете использовать метод sequences_to_texts
вашего токенизатора для преобразования этих индексов обратно в текстовые метки. Однако этот метод требует, чтобы индексы были корректно сопоставлены с вашими тегами:
# Преобразование индексов тегов в текст
predicted_tags = tag_tokenizer.sequences_to_texts(predicted_indices)
Обратите внимание, что predicted_indices
может содержать значения 0 для несуществующих тегов, из-за чего метод sequences_to_texts
не сможет правильно преобразовать их в текст. Нужно убедиться, что вы игнорируете нулевые индексы или заменяете их на подходящий тег.
3. Примеры кода
import numpy as np
# Предсказание с помощью модели
ypred = bidirect_model.predict(Xtest)
# Аргмакс для извлечения индексов тегов
predicted_indices = np.argmax(ypred, axis=-1)
# Убедитесь, что индексы не содержат нулей или обрабатываете их
# Например, заменяем 0 на 'O' (tag for 'no tag')
predicted_indices[predicted_indices == 0] = 1 # Замените на подходящий индекс
# Преобразование индексов в текстовые теги
predicted_tags = tag_tokenizer.sequences_to_texts(predicted_indices)
4. Заключение
Теперь вы сможете успешно преобразовать ваши предсказания модели в текстовые метки частей речи. Убедитесь, что ваш токенизатор корректно инициализирован и содержит все необходимые теги. Правильное преобразование предсказаний с использованием argmax
, а затем с помощью sequences_to_texts
позволит вам получить нужные результаты. Удачи в дальнейшем обучении модели и улучшении точности предсказаний!