Используйте scipy.integrate.quad с Tensorflow - PullRequest
0 голосов
/ 15 мая 2018

Я пытаюсь использовать scipy.integrate.quad с Tensorflow следующим образом. time и Lambda - два тензора с формой (None, 1).

def f_t(self, time, Lambda):
    h = Lambda * self.shape * time ** (self.shape - 1)
    S = tf.exp(-1 * Lambda * time ** self.shape)
    return h * S


def left_censoring(self, time, Lambda):
    return tf.map_fn(lambda x: integrate.quad(self.f_t,
                                              0.0,
                                              x[0], # it is not a float before evaluation
                                              args=(x[1],)),
                     tf.concat([time, Lambda], 1))

Однако я получаю сообщение об ошибке, как показано ниже:

File "J:\Workspace\Distributions.py", line 30, in <lambda>
    args=(x[1],)),
  File "I:\Anaconda3\envs\tensorflow\lib\site-packages\scipy\integrate\quadpack.py", line 323, in quad
    points)
  File "I:\Anaconda3\envs\tensorflow\lib\site-packages\scipy\integrate\quadpack.py", line 388, in _quad
    return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
TypeError: a float is required

X [0] - Тензор с shape = (). Это не значение с плавающей запятой до оценки. Возможно ли решить проблему? Как рассчитать интеграцию в Tensorflow?

1 Ответ

0 голосов
/ 16 мая 2018

Если у вас есть хотя бы TensorFlow 1.8.0, вам, вероятно, лучше всего использовать tf.contrib.integrate.odeint_fixed(), как этот код (проверено):

from __future__ import print_function
import tensorflow as tf

assert tf.VERSION >= "1.8.0", "This code only works with TensorFlow 1.8.0 or later."

def f( y, a ):
    return a * a

x = tf.constant( [ 0.0, 1.0, 2, 3, 4 ], dtype = tf.float32 )

i = tf.contrib.integrate.odeint_fixed( f, 0.0, x, method = "rk4" )

with tf.Session() as sess:
    res = sess.run( i )
    print( res )

выведет:

[0. 0.33333334 2.6666667 9. 21.333334]

, должным образом интегрируя x 2 через интервалы [0, 0] , [0, 1] , [0, 2] , [0, 3] и [0, 4] согласно x = [ 0, 1, 2, 3, 4 ] выше.(Примитивная функция x 2 равна ⅓ x 3 , поэтому дляпример 4 3 / 3 = 64/3 = 21 ⅓ .)


В противном случае, для более ранних версий TensorFlow, вот как исправить ваш код.

Таким образом, основная проблема заключается в том, что вы должны использовать tf.py_func() для отображения функции Python (scipy.integrate.quad() в этом случае) на тензор.tf.map_fn() отобразит другие операции TensorFlow и пропустит и ожидает тензоры в качестве операндов.Следовательно, x[ 0 ] не будет никогда простым плавающим числом, оно будет скалярным тензором и scipy.integrate.quad() не будет знать, что с этим делать.

Вы можетене полностью избавиться от tf.map_fn(), если только вы не хотите вручную циклически перебирать массивы.

Кроме того, scipy.integrate.quad() возвращает удвоение (float64)тогда как ваши тензоры - float32.

Я значительно упростил ваш код, потому что у меня нет доступа к остальному, и он выглядит слишком сложным по сравнению с ядром этого вопроса.Будет также выведен следующий код (проверено):

from __future__ import print_function
import tensorflow as tf
from scipy import integrate

def f( a ):
    return a * a

def integrated( f, x ):
    return tf.map_fn( lambda y: tf.py_func( 
               lambda z: integrate.quad( f, 0.0, z )[ 0 ], [ y ], tf.float64 ),
                      x )

x = tf.constant( [ 1.0, 2, 3, 4 ], dtype = tf.float64 )

i = integrated( f, x )

with tf.Session() as sess:
    res = sess.run( i )
    print( res )

:

[0.33333333 2.66666667 9. 21.33333333]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...