Raccoon 987
Raccoon 987

Reputation: 57

Numerical integration with scipy.integrate.quad_vec and Tensorflow

I am trying to apply code from the question answer taken from: Use scipy.integrate.quad with Tensorflow to my problem. For more simplicity - I want to integrate three 2D arrays containing Legendre polynomials of the 1st, 2nd and 3rd degrees, respectively.

from scipy.special import legendre
import numpy as np
import warnings
with warnings.catch_warnings():
    warnings.filterwarnings("ignore",category=FutureWarning)
    import tensorflow.compat.v1 as tf
    tf.disable_v2_behavior()
 

def f_2(n):
    def f_3(a):
        return np.arange(11, 20).reshape(3, 3) * legendre(n)(a) * legendre(n)(a) + np.ones((3, 3))
    return f_3


with tf.Session() as sess:
    def integrated(f, n):
        return tf.map_fn(fn=lambda x: tf.py_function(func=lambda z: integrate.quad_vec(f(z), 0.0, 4.0)[0],
                                                     #func=integrate.quad_vec(f, 0.0, 4.0)[0],
                                                     inp=[x],
                                                     Tout=tf.float64),
                         elems=n,
                         dtype=(tf.float64))
    res = sess.run(integrated(f_2, tf.constant([1, 2, 3], dtype = tf.int32)))
    print("res 1: ",  res )

This raises an error: ValueError: n must be a positive integer.

> [[{{node map/while/EagerPyFunc}}]]
> 
> During handling of the above exception, another exception occurred:
> 
> Traceback (most recent call last):   File
> "C:/Users/Enot/PycharmProjects/GPU-DL/cython_integral/test_tf_integral.py",
> line 178, in <module>
>     res = sess.run(integrated(f_2, tf.constant([1, 2], dtype = tf.int32)))   File
> "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\client\session.py",
> line 950, in run
>     run_metadata_ptr)   File "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\client\session.py",
> line 1173, in _run
>     feed_dict_tensor, options, run_metadata)   File "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\client\session.py",
> line 1350, in _do_run
>     run_metadata)   File "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\client\session.py",
> line 1370, in _do_call
>     raise type(e)(node_def, op, message) tensorflow.python.framework.errors_impl.InvalidArgumentError:
> ValueError: n must be a positive integer. Traceback (most recent call
> last):
> 
>   File
> "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\script_ops.py",
> line 207, in __call__
>     return func(device, token, args)   File "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\script_ops.py",
> line 109, in __call__
>     ret = self._func(*args)   File "C:/Users/Enot/PycharmProjects/GPU-DL/cython_integral/test_tf_integral.py",
> line 159, in <lambda>
>     func=lambda z: integrate.quad_vec(f(z), 0.0, 4.0)[0],   File "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\scipy\integrate\_quad_vec.py",
> line 305, in quad_vec
>     ig, err, rnd = _quadrature(x1, x2, f, norm_func)   File "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\scipy\integrate\_quad_vec.py",
> line 582, in _quadrature_gk21
>     return _quadrature_gk(a, b, f, norm_func, x, w, v)   File "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\scipy\integrate\_quad_vec.py",
> line 483, in _quadrature_gk
>     ff = f(c + h*x[i])   File "C:/Users/Enot/PycharmProjects/GPU-DL/cython_integral/test_tf_integral.py",
> line 137, in f_3
>     return np.arange(11, 20).reshape(3, 3) * legendre(n)(a) * legendre(n)(a) + np.ones((3, 3))   File
> "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\scipy\special\orthogonal.py",
> line 2077, in legendre
>     x, w, mu0 = roots_legendre(n1, mu=True)   File "C:\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\scipy\special\orthogonal.py",
> line 2021, in roots_legendre
>     raise ValueError("n must be a positive integer.")
> 
> ValueError: n must be a positive integer.
> 
> 
>    [[node map/while/EagerPyFunc (defined at
> /Users/Enot/PycharmProjects/GPU-DL/cython_integral/test_tf_integral.py:162)
> ]]
> 
> Errors may have originated from an input operation. Input Source
> operations connected to node map/while/EagerPyFunc: 
> map/while/TensorArrayReadV3 (defined at
> /Users/Enot/PycharmProjects/GPU-DL/cython_integral/test_tf_integral.py:165)
> 
> Original stack trace for 'map/while/EagerPyFunc':   File
> "/Users/Enot/PycharmProjects/GPU-DL/cython_integral/test_tf_integral.py",
> line 178, in <module>
>     res = sess.run(integrated(f_2, tf.constant([1, 2], dtype = tf.int32)))   File
> "/Users/Enot/PycharmProjects/GPU-DL/cython_integral/test_tf_integral.py",
> line 165, in integrated
>     dtype=(tf.float64)   File "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\map_fn.py",
> line 268, in map_fn
>     maximum_iterations=n)   File "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\control_flow_ops.py", line 2727, in while_loop
>     return_same_structure)   File "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\control_flow_ops.py", line 2238, in BuildLoop
>     pred, body, original_loop_vars, loop_vars, shape_invariants)   File
> "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\control_flow_ops.py", line 2163, in _BuildLoop
>     body_result = body(*packed_vars_for_body)   File "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\control_flow_ops.py", line 2682, in <lambda>
>     body = lambda i, lv: (i + 1, orig_body(*lv))   File "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\map_fn.py",
> line 257, in compute
>     packed_fn_values = fn(packed_values)   File "/Users/Enot/PycharmProjects/GPU-DL/cython_integral/test_tf_integral.py",
> line 162, in <lambda>
>     Tout=tf.float64   File "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\script_ops.py",
> line 392, in eager_py_func
>     return _internal_py_func(func=func, inp=inp, Tout=Tout, eager=True, name=name)   File
> "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\script_ops.py",
> line 281, in _internal_py_func
>     input=inp, token=token, Tout=Tout, name=name)   File "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\ops\gen_script_ops.py",
> line 74, in eager_py_func
>     "EagerPyFunc", input=input, token=token, Tout=Tout, name=name)   File
> "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\framework\op_def_library.py",
> line 788, in _apply_op_helper
>     op_def=op_def)   File "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\util\deprecation.py",
> line 507, in new_func
>     return func(*args, **kwargs)   File "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\framework\ops.py",
> line 3296, in create_op
>     op_def=op_def)   File "\Users\Enot\PycharmProjects\GPU-DL\venv\lib\site-packages\tensorflow\python\framework\ops.py",
> line 1692, in __init__
>     self._traceback = tf_stack.extract_stack()

thank you in advance.

=================================================================

Edit

Thank You for Your answer, Peter.

I need to iterate over Legendre degrees. Modifying your example - I get the error indicated in the question.

Change code from the answer I get the same error.

def integrated( n, i ):
    return tf.map_fn(fn=lambda x: tf.py_function(func=lambda z: integrate.quad( legendre( z ), 0.0, i)[0],
                                                 inp=[x],
                                                 Tout=tf.float64),
                     elems=n)
legendre_degree_tensor = tf.compat.v1.placeholder( tf.int32 )

with tf.Session() as sess:
    print( 'input' )
    legendre_degree = np.arange(1, 10).astype( np.int32 )
    print( input )
    input = 3.0
    res = sess.run( integrated( legendre_degree_tensor, input ), feed_dict= { legendre_degree_tensor: legendre_degree } )
    print("res 1: ",  res.reshape( 3, 3 ) )

Any ideas?

Upvotes: 0

Views: 1408

Answers (1)

Peter Szoldan
Peter Szoldan

Reputation: 4868

Ok based on your update to the question, here's the code that hopefully works for you (tested). I've omitted 'i' and the integration goes from 0.0 ... 10.0 but you can modify to include that. The main idea is that if you want to use the tensor's value in a python function, you first need to convert it to its value by the numpy() method.

from scipy.special import legendre
from scipy import integrate
import numpy as np
import warnings
with warnings.catch_warnings():
    warnings.filterwarnings("ignore",category=FutureWarning)
    import tensorflow.compat.v1 as tf
    tf.disable_v2_behavior()

def integrated( n ):
    return tf.map_fn(fn=lambda x: tf.py_function(func=lambda z: integrate.quad( legendre( z.numpy() ), 0.0, 10.0 )[0],
                                                inp=[x],
                                                Tout=tf.float64 ),
                     elems=n,
                     fn_output_signature = tf.float64 )
input_tensor = tf.compat.v1.placeholder( tf.int32 )
integrated_tensor = integrated( input_tensor )

with tf.Session() as sess:
    print( 'input' )
    input = np.arange(1, 10).astype( np.int32 )
    print( input )
    res = sess.run( integrated_tensor, feed_dict= { input_tensor: input } )
    print("res 1: ",  res.reshape( 3, 3 ) )

This will output:

input

[1 2 3 4 5 6 7 8 9]

res 1: [[5.00000000e+01 4.95000000e+02 6.17500000e+03]

[8.62537500e+04 1.29071875e+06 2.02334344e+07]

[3.27986609e+08 5.45295453e+09 9.24706365e+10]]

Which is, hopefully, what you wanted.

Upvotes: 1

Related Questions