Кастомный лосс в Керасе с софтмаксом на горячую

У меня есть модель, которая выводит Softmax, и я хотел бы разработать пользовательскую функцию потерь. Желаемое поведение:

1) Softmax в однократно (обычно я делаю numpy.argmax(softmax_vector) и устанавливаю этот индекс равным 1 в нулевом векторе, но это не разрешено в функции потерь).

2) Умножьте полученный горячий вектор на мою матрицу внедрения, чтобы получить вектор внедрения (в моем контексте: вектор слов, который связан с данным словом, где слова были токенизированы и присвоены индексам или классам для Softmax выход).

3) Сравните этот вектор с целевым (это может быть обычная функция потерь Кераса).

Я знаю, как написать пользовательскую функцию потерь в целом, но не для этого. Я нашел этот близкий вопрос (без ответа), но мой случай немного отличается, так как я хотел бы сохранить свой вывод softmax.


person Pablo    schedule 26.06.2018    source источник


Ответы (2)


В функции потери клиентов можно смешивать тензорный поток и керас. Как только вы получите доступ ко всем функциям Tensorflow, все станет очень просто. Я просто привожу пример того, как эта функция может быть реализована.

import tensorflow as tf
def custom_loss(target, softmax):
    max_indices = tf.argmax(softmax, -1)

    # Get the embedding matrix. In Tensorflow, this can be directly done
    # with tf.nn.embedding_lookup
    embedding_vectors = tf.nn.embedding_lookup(you_embedding_matrix, max_indices)

    # Do anything you want with normal keras loss function
    loss = some_keras_loss_function(target, embedding_vectors)

    loss = tf.reduce_mean(loss)
    return loss
person Fan Luo    schedule 26.06.2018
comment
Полезный ответ. Обратите внимание, однако, на важность порядка аргументов (фиксированный). Keras не допускает операций с неопределенными производными, когда они влияют на выходные значения, но они подходят для целей (написание ответа на основе этого). - person Pablo; 27.06.2018

Ответ Фань Луо указывает на правильное направление, но в конечном итоге не будет работать, поскольку включает непроизводные операции. Обратите внимание, что такие операции приемлемы для реального значения (функция потерь принимает реальное значение и прогнозируемое значение, непроизводные операции подходят только для реального значения).

Честно говоря, это то, о чем я спрашивал в первую очередь. Невозможно сделать то, что я хотел, но мы можем получить похожее и производное поведение:

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, тем больше будет конечный результат похож на one-hot.

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 в one-hot, вы можете выполнить шаги с 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)

Могут быть более элегантные решения (или менее требовательные к памяти, если разбиение матрицы встраивания на мозаику невозможно), так что не стесняйтесь исследовать больше.

person Pablo    schedule 27.06.2018