Tensorflow: дифференцируемые примитивы

У меня сложилось впечатление, что все примитивы тензорного потока дифференцируемы. Под этой «иллюзией» я написал эту функцию в надежде, что тензорный поток просто автоматически ее дифференцирует, и я смогу через нее поддерживать ошибки.

Ранг-весовая функция:

def ranked(a):
     lens     = tf.convert_to_tensor(tf.range(1, (tf.size(a) + 1)))
     rankw01  = tf.cast(tf.convert_to_tensor(tf.contrib.framework.argsort(tf.contrib.framework.argsort(a)) + 1),
                 tf.float64)
     rankw02  = tf.convert_to_tensor(rankw01 - ((tf.size(a) + 1)/2))
     rankw03  = tf.divide(rankw02, tf.reduce_sum(tf.gather(rankw02, tf.where(tf.greater(rankw02, 0)))))
     rankw04  = tf.cast(rankw03, tf.float32)

     return rankw04

К сожалению, функция работает, как и ожидалось, в прямом проходе, но не работает в обратном проходе, потому что производная не существует (из-за ошибки, которую я продолжаю получать).

Функция поясняется на прикрепленном изображении:

введите здесь описание изображения

У меня есть следующие вопросы:

1: Почему я не могу взять производную от приведенной выше функции.

2: Если это проблема реализации, можете ли вы предложить, как я могу переписать его, чтобы я мог использовать его производные и ошибки обратного распространения?

3: Все ли операции тензорного потока дифференцируемы?


person Baba Yara    schedule 14.08.2018    source источник
comment
Как вы различаете? Я бы попробовал версию без tf.convert_to_tensor вызовов. Если ввод вашей функции не является тензором (например, если это массив numpy), тензорный поток не будет знать, где он был преобразован в тензор.   -  person DomJack    schedule 19.08.2018
comment
Спасибо за предложение, @DomJack. Я вернулся и очистил код, начиная с вашего предложения, и теперь у меня есть работающая функция взвешивания рангов, которая дифференцируема.   -  person Baba Yara    schedule 25.08.2018


Ответы (1)


Поэтому я последовал совету @DomJack и удалил вызовы tf.convert_to_tensor и полностью убрался в доме. Теперь функция дифференцируема.

def ranked(a):
    rankw01  = tf.cast(tf.contrib.framework.argsort(tf.contrib.framework.argsort(a)) + 1, tf.float32)
    rankw02  = rankw01 - tf.cast((tf.shape(a)[-1] + 1)/2, tf.float32)
    rankw03  = tf.div(rankw02, tf.reduce_sum(tf.nn.relu(rankw02), axis = -1, keepdims=True))

    return rankw033
person Baba Yara    schedule 25.08.2018
comment
Рад, что вы попали туда :). Краткое примечание: убедитесь, что ваше подразделение делает правильные вещи в (tf.shape(a)[-1] + 1)/2 (целое деление против деления с плавающей запятой) - в зависимости от вашей версии python/независимо от того, используете ли вы from __future__ import division. Возможно, вам придется сделать гипс перед разделением. - person DomJack; 26.08.2018