将scipy.integrate.quad与Tensorflow一起使用

时间:2018-05-15 17:52:30

标签: math tensorflow scipy

我正在尝试将scipy.integrate.quad与Tensorflow一起使用如下。 timeLambda是两个有形状的张量(无,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 =()的Tensor。在评估之前它不是浮点值。有可能解决问题吗?我应该如何计算Tensorflow中的集成?

1 个答案:

答案 0 :(得分:3)

如果您至少拥有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]

[0,0] x 2 >, [0,1] [0,2] [0 ,3] ,以及 [0,4] ,符合上述x = [ 0, 1, 2, 3, 4 ]。 ( x 2 的原始函数是 ⅓x 3 < / strong>,例如 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(),除非你想手动循环numpy数组。

此外,scipy.integrate.quad()返回一个double(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]