4

I've just started learning tensorflow, and basically I'm learning to do various numerical computations using tensorflow rather than directly jumping into its use in ML. I'm doing this on the Google Cloud Platform, where I came across this problem and got stuck.

Roots of 4th degree polynomial

I'm using lazy evaluation and I can make instances of a0, a1, a2...,a4 in the tensorflow graph using placeholders, also I can write out the function. But how do I make the initial guess using tensorflow? And moreover, even if I get value of x0 how do I apply loop using tf.while_loop I went through its documentation and this post, but I'm still clueless as to how do I proceed. I tried to find a post with similar question or content but couldn't find a one in which tensorflow is used. It would be great if I could get insights or way to use intrinsic tensorflow functions and commands :) Thanks in advance!

TheSHETTY-Paradise
  • 1,024
  • 2
  • 9
  • 19

2 Answers2

2

When I execute the first example from here I get these values. Please note that the equation is different.

1.4999999969612645

1.411188880378198

1.4142132016669995

1.4142135623730898

But this seems to be a good example to start with.

import tensorflow as tf

h = tf.constant(.00000001, dtype='float64')
eps = tf.constant(.000001, dtype='float64')
b = tf.constant(2.0, tf.float64)

def f(x):
    return tf.subtract( tf.multiply(x , x ) , 2. )

def fp(x):
    return  tf.divide( tf.subtract( f(tf.add(x, h)) ,
                                    f(x)
                                  ) ,
                       h
                     )

def fpp(x):
    return tf.divide( tf.subtract( fp( tf.add(x , h)) ,
                                   fp(x)
                                 ),
                       h
                     )

def cond(i, x_new, x_prev):
    return tf.logical_and( i < 5,
            tf.less_equal( tf.abs( tf.cast(tf.subtract( x_new ,
                                                       x_prev
                                                     ),dtype='float64')),
                          eps
                        )
                        )

def body( i, x_new, x_prev ):
    fx = f( x_prev )
    fpx = fp( x_prev )
    x_new = tf.subtract( x_prev ,
                         tf.divide( b * fx * fpx  ,
                                    tf.subtract(b * fpx * fpx,
                                                fx * fpp( x_prev )
                                               )
                                  )
                       )

    xnew = tf.Print(x_new, [x_new], message="The root is : ")

    with tf.control_dependencies([x_new,xnew]):
        x_prev = tf.identity(xnew)

    return [i + 1, xnew, x_prev ]

sess = tf.Session()
sess.run(tf.global_variables_initializer())


print( sess.run(tf.while_loop(cond, body, [1, b - fpp(b), b])) )

The root is : [1.4999999969612645]

The root is : [1.411188880378198]

The root is : [1.4142132016669995]

The root is : [1.4142135623730898]

[5, 1.4142135623730898, 1.4142135623730898]

Mohan Radhakrishnan
  • 3,002
  • 5
  • 28
  • 42
  • Say, I am not clear on why you used `tf.cast` in the `cond` function? These were already floats, so I was not clear on why you recasted them as floats? This is just for clarification as I was going through the code. – krishnab Oct 19 '18 at 18:29
  • Thanks for the answer, according to what I checked, one can remove the cast function and wouldn't made a difference. But as a force of habit, it's ok. – Héctor Neri Nov 01 '18 at 23:05
  • I think I added that cast and forgot about it because it just worked. – Mohan Radhakrishnan Nov 02 '18 at 02:37
0

Here is my implementation with eager evaluation, use tensorflow GradientTape for calculating the derivatives:

import tensorflow as tf
print("Tensorflow-CPU version is {0}".format(tf.__version__))

stop_variation = 0.00001 # Variation threshold from previous iteration to stop iteration

def halley(i, coeffs, x_new, x_prev):
    """
    Halley's Method implementation
    """

    a0 = coeffs[0]
    a1 = coeffs[1]
    a2 = coeffs[2]
    a3 = coeffs[3]
    a4 = coeffs[4]

    with tf.GradientTape() as g:
      g.watch(x_new)
      with tf.GradientTape() as gg:
        gg.watch(x_new)
        f =  a0 + a1 * x_new + a2 *  x_new**2 + a3 * x_new**3 + a4 * x_new**4
      df_dx = gg.gradient(f, x_new)
    df_dx2 = g.gradient(df_dx, x_new)

    numerator = 2 * f * df_dx
    denominator = 2 * df_dx*df_dx - f*df_dx2
    new_x  = x_new - (numerator/denominator)
    prev_x = x_new
    print("Root approximation in step {0} = {1}".format(i, new_x))
    return [i+1, coeffs, new_x, prev_x]

def condition(i, a, x_new, x_prev):
    variation = tf.abs(x_new - x_prev)
    return tf.less(stop_variation, variation)

tf.enable_eager_execution()

a = tf.constant(
        [2.0, -4.0, 1.0, 2.0, 0.0]
)  
x = tf.constant(40.0)
xprev = tf.constant(100.0)

roots =  tf.while_loop(     
          condition, 
          halley, 
          loop_vars=[1, a, x, xprev],
          maximum_iterations=1000)

print("Result after {0} iterations is {1}.".format(roots[0]-1, roots[2]))
dmbarreiro
  • 154
  • 2
  • 10