将scipy.integrate.quad与Tensorflow一起使用 [英] Use scipy.integrate.quad with Tensorflow

查看:59
本文介绍了将scipy.integrate.quad与Tensorflow一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正尝试将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)返回h * Sdef left_censoring(自我,时间,Lambda):返回tf.map_fn(lambda x:integration.quad(self.f_t,0.0,x [0],#计算前不是浮点数args =(x [1],)),tf.concat([time,Lambda,1)) 

但是,出现以下错误:

 文件"J:\ Workspace \ Distributions.py",第30行,位于< lambda>中.args =(x [1],)),文件"I:\ Anaconda3 \ envs \ tensorflow \ lib \ site-packages \ scipy \ integrate \ quadpack.py",第323行,在四边形中点)_quad中的文件"I:\ Anaconda3 \ envs \ tensorflow \ lib \ site-packages \ scipy \ integrate \ quadpack.py",行388return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)TypeError:需要浮点数 

X [0]是具有shape =()的张量.它不是评估前的浮点值.有可能解决问题吗?我应该如何计算Tensorflow中的积分?

解决方案

如果您至少具有TensorFlow 1.8.0,则最好使用 from __future__ import print_function将tensorflow导入为tfassert tf.VERSION >= "1.8.0", "此代码仅适用于 TensorFlow 1.8.0 或更高版本."def f(y,a):返回一个* ax = tf.constant([0.0,1.0,2,3,4],dtype = tf.float32)i = tf.contrib.integrate.odeint_fixed(f,0.0,x,method ="rk4")与tf.Session()作为sess:res = sess.run(i)打印(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 ,例如 4 3 /3 = 64/3 > = 21⅓ .)


否则,对于TensorFlow的早期版本,这是修复代码的方法.

因此,主要问题是您必须使用 tf.py_func() 映射Python函数( tf.map_fn() 将映射其他TensorFlow操作并传递,并期望张量作为操作数.因此 x [0] 从不是简单的浮点数,它将是标量张量和 tf.map_fn() 或者,除非您想手动循环遍历 numpy 数组.

此外, scipy.integrate.quad() 返回一个double(float64),而您的张量为float32.

我已经大大简化了您的代码,因为我无法访问它的其余部分,并且与该问题的核心相比,它看起来太复杂了.以下代码(经过测试):

来自__future__的

  __ import print_function将tensorflow导入为tf从scipy导入集成def f(a):返回一个* adef集成(f,x):返回tf.map_fn(lambda y:tf.py_func(lambda z:integration.quad(f,0.0,z)[0],[y],tf.float64),X )x = tf.constant([1.0,2,3,4],dtype = tf.float64)i =积分(f,x)与tf.Session()作为sess:res = sess.run(i)打印(res) 

还将输出:

[ 0.33333333 2.66666667 9. 21.33333333]

I am trying to use scipy.integrate.quad with Tensorflow as following. time and Lambda are two Tensors with shape (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))

However, I get an error as below:

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] is a Tensor with shape=(). It is not a float value before evaluation. Is it possible to solve the problem? How should I calculate integration in Tensorflow?

解决方案

If you have at least TensorFlow 1.8.0, you're probably best off using tf.contrib.integrate.odeint_fixed() like this code (tested):

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 )

will output:

[ 0. 0.33333334 2.6666667 9. 21.333334 ]

properly integrating x2 over the intervals of [ 0, 0 ], [ 0, 1 ], [ 0, 2 ], [ 0, 3 ], and [ 0, 4 ] as per x = [ 0, 1, 2, 3, 4 ] above. (The primitive function of x2 is ⅓ x3, so for example 43 / 3 = 64/3 = 21 ⅓.)


Otherwise, for earlier TensorFlow versions, here's how to fix your code.

So the main issue is that you have to use tf.py_func() to map a Python function (scipy.integrate.quad() in this case) on a tensor. tf.map_fn() will map other TensorFlow operations and passes and expects tensors as operands. Therefore x[ 0 ] will never be a simple float, it will be a scalar tensor and scipy.integrate.quad() will not know what to do with that.

You can't completely get rid of tf.map_fn() either, unless you want to manually loop over numpy arrays.

Furthermore, scipy.integrate.quad() returns a double (float64), whereas your tensors are float32.

I've simplified your code a lot, because I don't have access to the rest of it and it looks too complicated compared to the core of this question. The following code (tested):

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 )

will also output:

[ 0.33333333 2.66666667 9. 21.33333333]

这篇关于将scipy.integrate.quad与Tensorflow一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆