Ответ Фан Луо указывает в правильном направлении, но в конечном итоге не сработает, потому что он включает в себя не производные операции. Обратите внимание, что такие операции являются приемлемыми для реального значения (функция потерь принимает реальное значение и прогнозируемое значение, а не производные операции подходят только для реального значения).
Чтобы быть справедливым, это было то, что я спрашивал в первую очередь. не возможно сделать то, что я хотел, но мы можем получить аналогичное и выводимое поведение:
1) Поэлементная мощность значений softmax. Это делает меньшие значения намного меньшими. Например, при мощности 4 [0,5, 0,2, 0,7] становится [0,0625, 0,0016, 0,2400] . Обратите внимание, что 0,2 сравнимо с 0,7, но 0,0016 незначительно по отношению к 0,24. Чем выше my_power, тем больше будет схож с финалом.
soft_extreme = Lambda(lambda x: x ** my_power)(softmax)
2) Важно, что нормализованные векторы как softmax, так и one-hot, но не наш "soft_extreme". Сначала найдите сумму массива:
norm = tf.reduce_sum(soft_extreme, 1)
3) Нормализовать soft_extreme:
almost_one_hot = Lambda(lambda x: x / norm)(soft_extreme)
Примечание : слишком высокое значение my_power в 1) приведет к появлению NaN. Если вам нужно лучшее преобразование softmax в одну горячую версию, то вы можете выполнять шаги с 1 по 3 два или более раз подряд.
4) Наконец, мы хотим вектор из словаря. Поиск запрещен, но мы можем взять средний вектор, используя матричное умножение. Поскольку наше soft_normalized похоже на однократное кодирование, это среднее будет похоже на вектор, связанный с самым высоким аргументом (исходное предполагаемое поведение). Чем выше my_power в (1), тем честнее это будет:
target_vectors = tf.tensordot(almost_one_hot, embedding_matrix, axes=[[1], [0]])
Примечание : Это не будет работать напрямую с пакетами! В моем случае я изменил свой «один горячий» (с [batch, dictionary_length] до [batch, 1, dictionary_length] , используя tf.reshape . Затем разложил плитку по размеру пакета embedding_matrix и наконец использовал:
predicted_vectors = tf.matmul(reshaped_one_hot, tiled_embedding)
Могут быть более изящные решения (или менее требовательные к памяти, если мозаика встраивания не является опцией), поэтому не стесняйтесь исследовать больше.