Моя функция стоимости включает в себя вычисление log(det(A)) (при условии, что det(A) положительно, поэтому журнал имеет смысл, но A не является эрмитовым, так что разложение Холецкого здесь неприменимо). Когда det(A) очень большой/малый, прямой вызов det(A) вызовет переполнение/недостаточное переполнение. Чтобы обойти это, можно использовать математический факт, что
журнал (det (A)) = Tr (журнал (A)),
где последнее можно оценить с помощью разложения LU (что более эффективно, чем собственное значение/SVD). Этот алгоритм был реализован в numpy как numpy.linalg. slogdet, поэтому проблема в том, как вызвать numpy из TensorFlow.
Вот что я пробовал
import numpy as np
import tensorflow as tf
from tensorflow.python.framework import function
def logdet_np(a):
_, l = np.linalg.slogdet(a)
return l
def logdet1(a):
return tf.py_func(logdet_np, [a], tf.float64)
@function.Defun(tf.float64, func_name='LogDet')
def logdet2(a):
return tf.py_func(logdet_np, [a], tf.float64)
with tf.Session() as sess:
a = tf.constant(np.eye(500)*10.)
#print(sess.run(logdet1(a)))
print(sess.run(logdet2(a)))
Сначала я определяю функцию python для передачи результата numpy. Затем я определил две функции logdet
, используя tf.py_func
. Вторая функция украшена function.Defun
, которая позже используется для определения функций TensorFlow и их градиентов. Тестируя их, я обнаружил, что первая функция logdet1
работает и дает правильный результат. Но вторая функция logdet2
возвращает KeyError.
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-
packages/tensorflow/python/ops/script_ops.py in __call__(self, token, args)
77 def __call__(self, token, args):
78 """Calls the registered function for `token` with args."""
---> 79 func = self._funcs[token]
80 if func is None:
81 raise ValueError("callback %s is not found" % token)
KeyError: 'pyfunc_0'
Мой вопрос: что не так с декоратором Defun
? Почему он конфликтует с py_func
? Как я могу правильно обернуть функции numpy в TensorFlor?
Оставшаяся часть определения градиента для logdet
связана с вопросом дифференцирование детерминанта матрицы в тензорном потоке. Согласно решению этого вопроса, можно попытаться написать
@function.Defun(tf.float64, tf.float64, func_name='LogDet_Gradient')
def logdet_grad(a, grad):
a_adj_inv = tf.matrix_inverse(a, adjoint=True)
out_shape = tf.concat([tf.shape(a)[:-2], [1, 1]], axis=0)
return tf.reshape(grad, out_shape) * a_adj_inv
@function.Defun(tf.float64, func_name='LogDet', grad_func=logdet_grad)
def logdet(a):
return tf.py_func(logdet_np, [a], tf.float64, stateful=False, name='LogDet')
Приведенный выше код будет работать, если удастся решить конфликт между Defun
и py_func
, что является ключевым вопросом, который я поднял выше.