Автор использует маску и кросс-энтропию softmax с логитами. Я пока не понимаю, как реализовать это в Керасе.
Что касается кросс-энтропии softmax с логитами, вы делаете это правильно. softmax_cross_entropy_with_logits
как функция потерь + отсутствие функции активации на последнем слое - это то же самое, что ваш подход с categorical_crossentropy
в качестве потери + softmax
активации на последнем слое. Разница лишь в том, что последний численно менее стабилен. Если это окажется проблемой для вас, вы можете (если ваш сервер Keras имеет тензор потока) просто передать tf.softmax_cross_entropy_with_logits
в качестве вашей потери. Если у вас есть другой бэкэнд, вам придется искать там эквивалент.
Что касается маскировки, я не уверен, полностью ли я понимаю, что делает автор. Однако в Keras слой Embedding
имеет параметр mask_zero
, который можно установить на True
. В этом случае все временные шаги, которые имеют 0
, будут игнорироваться во всех дальнейших вычислениях. В вашем источнике маскируется не 0
, поэтому вам придется соответствующим образом скорректировать индексы. Если это не сработает, в Keras есть слой Masking
, который вы можете поместить перед своим повторяющимся слоем, но у меня мало опыта с этим.
Моя главная проблема здесь с return_sequence = True. Автор не
кажется, что он использует
Что заставляет вас думать, что он им не пользуется? То, что это ключевое слово не появляется в коде, ничего не значит. Но я тоже не уверен. Код довольно старый, и я больше не нахожу его в документах, которые могли бы сказать, каковы значения по умолчанию.
В любом случае, если вы хотите использовать return_sequences=False
(по любой причине), имейте в виду, что это меняет форму вывода слоя:
- с
return_sequences=True
форма вывода (batch_size, timesteps, features)
- с
return_sequences=False
выходная форма (batch_size, features)
Ошибка, которую вы получаете, в основном говорит о том, что выход вашей сети имеет на одно измерение меньше целевых значений y
, которые вы передаете.
Поэтому мне кажется, что return_sequences=True
- это то, что вам нужно, но без дополнительной информации трудно сказать.
Тогда относительно TimeDistributed . Я не совсем уверен, чего вы добиваетесь, но цитирую документы:
Эта оболочка применяет слой к каждому временному фрагменту ввода.
Ввод должен быть не менее 3D , а размер индекса один будет считаться временным измерением.
(ударение мое)
Я не уверен из вашего вопроса, в каком случае происходит пустое утверждение.
Если у вас есть рекуррентный слой с return_sequences=False
ранее, вы снова пропускаете измерение (хотя я не могу сказать вам, почему утверждение пусто).
Если у вас есть рекуррентный слой с return_sequences=True
ранее, он должен работать, но он будет совершенно бесполезен, так как Dense
в любом случае применяется с распределением времени. Если я не ошибаюсь, это поведение слоя Dense
было изменено в некоторых старых версиях Keras (они действительно должны обновить пример и перестать использовать Dense
!). Поскольку код, на который вы ссылаетесь, довольно старый, вполне возможно, что TimeDistributed
тогда был необходим, но больше не нужен.
Если ваш план состоял в том, чтобы восстановить недостающее измерение, TimeDistributed
вам не поможет, но RepeatVector
поможет. Но, как уже говорилось, в этом случае лучше использовать return_sequences=True
в первую очередь.