Кастомные потери в керасе с softmax до одноразовых - PullRequest
0 голосов
/ 26 июня 2018

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

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

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

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

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

Ответы [ 2 ]

0 голосов
/ 27 июня 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, тем больше будет схож с финалом.

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)

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

0 голосов
/ 26 июня 2018

В функции потери клиента можно смешивать тензор потока и керас. Как только вы получите доступ ко всем функциям 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...