Challenge Solution: Getting started with TensorFlow

Challenge Exercise

Use TensorFlow to find the roots of a fourth-degree polynomial using Halley's Method. The five coefficients (i.e. $a_0$ to $a_4$) of

$f(x) = a_0 + a_1 x + a_2 x^2 + a_3 x^3 + a_4 x^4$

will be fed into the program, as will the initial guess $x_0$. Your program will start from that initial guess and then iterate one step using the formula:

If you got the above easily, try iterating indefinitely until the change between $x_n$ and $x_{n+1}$ is less than some specified tolerance. Hint: Use tf.while_loop

Iterate one step

Note that we use TensorFlow's built-in automatic differentiation!


In [4]:
import tensorflow as tf
import numpy as np

class Halley:
  def __init__(self, a):
    self.f = lambda x: a[0] + a[1] * x + a[2] * tf.pow(x, 2) + a[3] * tf.pow(x, 3) + a[4] * tf.pow(x, 4)
    self.df = lambda x: tf.gradients(self.f(x), x)[0]  # TensorFlow does automatic differentiation!
    self.ddf = lambda x: tf.gradients(self.df(x), x)[0]

  def compute_one_iteration(self, x):
    return x - ((2 * self.f(x) * self.df(x)) / (2 * tf.pow(self.df(x), 2) - self.f(x) * self.ddf(x)))


# answer is supposed to be 7.411
with tf.Session() as sess:
  a = [-1.0,1.0,12.0,-4.0,1.0]
  x0 = tf.constant(12.0)
  halley = Halley(a)
  answer = halley.compute_one_iteration(x0)
  result = sess.run(answer)
  print(result)


7.4111586

Iterate 3 times

... by writing the compute 3 times


In [5]:
import tensorflow as tf
import numpy as np

class Halley:
  def __init__(self, a):
    self.f = lambda x: a[0] + a[1] * x + a[2] * tf.pow(x, 2) + a[3] * tf.pow(x, 3) + a[4] * tf.pow(x, 4)
    self.df = lambda x: tf.gradients(self.f(x), x)[0]
    self.ddf = lambda x: tf.gradients(self.df(x), x)[0]

  def compute_one_iteration(self, x):
    return x - ((2 * self.f(x) * self.df(x)) / (2 * tf.pow(self.df(x), 2) - self.f(x) * self.ddf(x)))


# answer is supposed to be [7.4111586, 4.459961, 2.2138097]
with tf.Session() as sess:
  a = [-1.0,1.0,12.0,-4.0,1.0]
  x0 = tf.constant(12.0)
  halley = Halley(a)
  x1 = halley.compute_one_iteration(x0)
  x2 = halley.compute_one_iteration(x1)
  x3 = halley.compute_one_iteration(x2)
  result = sess.run([x1, x2, x3])
  print(result)


[7.4111586, 4.459961, 2.2138097]

Iterate until condition

... using tf.while


In [14]:
import tensorflow as tf
import numpy as np

import tensorflow as tf
import numpy as np

class Halley:
  def __init__(self, a):
    self.f = lambda x: a[0] + a[1] * x + a[2] * tf.pow(x, 2) + a[3] * tf.pow(x, 3) + a[4] * tf.pow(x, 4)
    self.df = lambda x: tf.gradients(self.f(x), x)[0]
    self.ddf = lambda x: tf.gradients(self.df(x), x)[0]

  def compute_one_iteration(self, x):
    return x - ((2 * self.f(x) * self.df(x)) / (2 * tf.pow(self.df(x), 2) - self.f(x) * self.ddf(x)))

  def prev_and_curr(self, iterno, prev, x):
    return iterno+1, x, self.compute_one_iteration(x)

  def compute(self, x0, maxiter, epsilon):
    return tf.while_loop(lambda i, prev, x: tf.logical_and(tf.abs(prev-x) > epsilon, i < maxiter), 
                         self.prev_and_curr, (0, x0-2*epsilon, x0))
  
# init parameters
# answer is supposed to be -0.31365424 or 0.259158
with tf.Session() as sess:
  a = [-1.0,1.0,12.0,-4.0,1.0]
  x0 = tf.constant(12.0)
  halley = Halley(a)
  xn = halley.compute(x0, 100, 0.01)
  result = sess.run(xn)
  print(result[2])


0.25915924

Copyright 2018 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License