예제 #1
0
    def test_invalid_interpolate_parameter_value(self):
        """Test where a value to interpolate lies outside the spline points."""

        x_data1 = np.linspace(-5.0, 5.0, num=11)
        x_data2 = np.linspace(0.0, 10.0, num=11)
        x_series = np.array([x_data1, x_data2])
        y_data1 = [1.0 / (1.0 + x * x) for x in x_data1]
        y_data2 = [1.0 / (2.0 + x * x) for x in x_data2]
        y_series = np.array([y_data1, y_data2])
        x_data_series = tf.stack(x_series, axis=0)
        y_data_series = tf.stack(y_series, axis=0)

        # num_test_values = 3
        search_args = tf.constant([[-5.2, 0.0, 5.3], [2.2, 1.8, 5.0]],
                                  dtype=tf.float64)
        x_test = tf.stack(search_args, axis=0)
        spline = cubic.build_spline(x_data_series, y_data_series)

        msg = ("Failed to catch that the test vector data lies outside of "
               "spline range")

        with self.assertRaises(tf.errors.InvalidArgumentError, msg=msg) as cm:
            self.evaluate(cubic.interpolate(x_test, spline,
                                            validate_args=True))
        print(cm.exception)
예제 #2
0
    def test_error_calc(self):
        """Test that the deviation between the interpolated values and the actual values.

       This should be less than 0.02. This value was derived by running the
       same test with scipy cubic interpolation
    """
        sampling_points = 1000
        spline_x = np.linspace(0.0, 10.0, num=11, dtype=np.float64)
        spline_y = [1.0 / (1.0 + x * x) for x in spline_x]
        x_series = np.array([spline_x])
        y_series = np.array([spline_y])
        spline = cubic.build_spline(x_series, y_series)

        # There is an error if we go to 10.0
        test_range_x = np.linspace(0.0,
                                   9.99,
                                   num=sampling_points,
                                   dtype=np.float64)
        search_args = tf.constant(np.array([test_range_x]), dtype=tf.float64)
        projected_y = cubic.interpolate(search_args, spline)
        expected_y = tf.constant([[1.0 / (1.0 + x * x) for x in test_range_x]],
                                 dtype=tf.float64)
        errors = expected_y - projected_y
        deviation = self.evaluate(tfp.stats.stddev(errors[0], sample_axis=0))
        limit = 0.02
        self.assertLess(deviation, limit)
예제 #3
0
    def test_compare_shape_conformance_of_interpolate(self):
        """Test that the shape of the result of the interpolate method is correct.

    i.e.
    given
    x_points.shape (num_splines, spline_length)
    y_points.shape (num_splines, spline_length)
    x_test.shape (num_splines, num_test_values)

    then interpolate(x_test, spline ) -> shape(num_splines, num_test_values)
    """

        # num splines = 2
        # spline_length = 11
        x_data1 = np.linspace(-5.0, 5.0, num=11)
        x_data2 = np.linspace(0.0, 10.0, num=11)
        x_series = np.array([x_data1, x_data2])
        y_data1 = [1.0 / (1.0 + x * x) for x in x_data1]
        y_data2 = [1.0 / (2.0 + x * x) for x in x_data2]
        y_series = np.array([y_data1, y_data2])

        # num_test_values = 3
        search_args = tf.constant([[-1.2, 0.0, 0.3], [2.2, 1.8, 5.0]],
                                  dtype=tf.float64)

        x_data_series = tf.stack(x_series, axis=0)
        y_data_series = tf.stack(y_series, axis=0)
        x_test = tf.stack(search_args, axis=0)

        spline = cubic.build_spline(x_data_series, y_data_series)
        predicted = cubic.interpolate(x_test, spline)

        self.assertAllEqual(tf.shape(x_test), tf.shape(predicted))

        # num_test_values = 13
        search_args11 = tf.constant(
            [[-1.2, 0.0, 0.3, 1.2, 2.1, 0.8, 0.0, 0.3, 1.2, 2.1, 0.8],
             [2.2, 1.8, 5.0, 2.2, 1.8, 5.0, 5.0, 2.2, 1.8, 5.0, 2.2]],
            dtype=tf.float64)

        x_test11 = tf.stack(search_args11, axis=0)
        predicted11 = cubic.interpolate(x_test11, spline)

        self.assertAllEqual(tf.shape(x_test11), tf.shape(predicted11))
예제 #4
0
    def test_invalid_interpolate_parameter_shape(self):
        """Test shape(x_points)[0] != shape(test_x)[0]."""

        x_data1 = np.linspace(-5.0, 5.0, num=11)
        x_data2 = np.linspace(0.0, 10.0, num=11)
        x_series = np.array([x_data1, x_data2])
        y_data1 = [1.0 / (1.0 + x * x) for x in x_data1]
        y_data2 = [1.0 / (2.0 + x * x) for x in x_data2]
        y_series = np.array([y_data1, y_data2])
        x_data_series = tf.stack(x_series, axis=0)
        y_data_series = tf.stack(y_series, axis=0)

        search_args = tf.constant([[-1.2, 0.0, 0.3]], dtype=tf.float64)
        x_test = tf.stack(search_args, axis=0)
        spline = cubic.build_spline(x_data_series, y_data_series)

        msg = "Failed to catch that the test vector has less rows than x_points"
        with self.assertRaises(ValueError, msg=msg):
            cubic.interpolate(x_test, spline)
예제 #5
0
    def interpolate(self, x_values, y_values, name=None):
        """Performs 2-D interpolation on a specified set of points.

    Args:
      x_values: Real-valued `Tensor` of shape `batch_shape + [num_points]`.
        Defines the x-coordinates at which the interpolation should be
        performed. Note that `batch_shape` should be the same as in the
        underlying data.
      y_values: A `Tensor` of the same shape and `dtype` as `x_values`.
        Defines the y-coordinates at which the interpolation should be
        performed.
      name: Python `str` name prefixed to ops created by this function.
        Default value: `None` which is mapped to the default name
        `interpolate`.

    Returns:
      A `Tensor` of the same shape and `dtype` as `x_values`. Represents the
      interpolated values of the function on for the coordinates
      `(x_values, y_values)`.
    """
        name = name or self._name + "_interpolate"
        with tf.name_scope(name):
            x_values = tf.convert_to_tensor(x_values,
                                            dtype=self._dtype,
                                            name="x_values")
            y_values = tf.convert_to_tensor(y_values,
                                            dtype=self._dtype,
                                            name="y_values")

            # Broadcast `y_values` to the number of `x_data` points
            y_values = tf.expand_dims(y_values, axis=-2)
            # For each `x_data` point interpolate values of the function at the
            # y_values. Shape of `xy_values` is
            # batch_shape + `[num_x_data_points, num_points]`.
            xy_values = cubic.interpolate(y_values,
                                          self._spline_yz,
                                          name="interpolation_in_y_direction")
            # Interpolate the value of the function along x-direction
            # Prepare xy_values for linear interpolation. Put the batch dims in front
            xy_rank = xy_values.shape.rank
            perm = [xy_rank - 1] + list(range(xy_rank - 1))
            # Shape [num_points] + batch_shape + [num_x_data_points]
            yx_values = tf.transpose(xy_values, perm=perm)
            # Get the permutation to the original shape
            perm_original = list(range(1, xy_rank)) + [0]
            # Reshape to [num_points] + batch_shape + [1]
            x_values = tf.expand_dims(tf.transpose(x_values, [xy_rank - 2] +
                                                   list(range(xy_rank - 2))),
                                      axis=-1)
            # Interpolation takes care of braodcasting
            z_values = linear.interpolate(x_values, self._xdata, yx_values)
            return tf.squeeze(tf.transpose(z_values, perm=perm_original),
                              axis=-2)
예제 #6
0
    def interpolate(self, x_values, y_values, name=None):
        """Performs 2-D interpolation on a specified set of points.

    Args:
      x_values: Real-valued `Tensor` of rank 1. Defines the x-coordinates at
        which the interpolation should be performed.
      y_values: Rank 1 `Tensor` of the same `dtype` as `x_values`. Defines the
        y-coordinates at which the interpolation should be performed.
      name: Python `str` name prefixed to ops created by this function.
        Default value: `None` which is mapped to the default name
        `interpolate`.

    Returns:
      A `Tensor` of the same `dtype` as `x_values` and of shape
      `x_values.shape + y_values.shape`. Represents the interpolated values of
      the function on the grid `[x_values, y_values]`
    """
        name = name or self._name + "_interpolate"
        with tf.name_scope(name):
            x_values = tf.convert_to_tensor(x_values,
                                            dtype=self._dtype,
                                            name="x_values")
            y_values = tf.convert_to_tensor(y_values,
                                            dtype=self._dtype,
                                            name="y_values")

            num_x_data = self._xdata.shape.as_list()[-1]
            num_y_values = y_values.shape.as_list()[-1]
            # Broadcast `y_values` to the number of `x_data` points
            y_values = (
                tf.expand_dims(y_values, 0) +
                tf.zeros([num_x_data, num_y_values], dtype=y_values.dtype))
            # For each `x_data` point interpolate values of the function at the
            # y_values. Shape of `xy_values` is `[num_x_data, num_y_values]`.
            xy_values = cubic.interpolate(y_values,
                                          self._spline_yz,
                                          name="interpolation_in_y_direction")
            # Interpolate the value of the function along x-direction
            # Prepare xy_values for linear interpolation. Put the batch dims in front
            xy_rank = xy_values.shape.rank
            perm = [xy_rank - 1] + list(range(xy_rank - 1))
            yx_values = tf.transpose(xy_values, perm=perm)
            # Get the permutation to the original shape
            perm_original = list(range(1, xy_rank)) + [0]
            # Interpolation takes care of braodcasting
            z_values = linear.interpolate(x_values, self._xdata, yx_values)
            return tf.transpose(z_values, perm=perm_original)
예제 #7
0
    def test_dtype_conversion_float64_32(self):
        """Test specifying float64 data but requiring conversion to float32."""
        x_data1 = np.linspace(-5.0, 5.0, num=11, dtype=np.float64)
        x_data2 = np.linspace(0.0, 10.0, num=11, dtype=np.float64)
        x_series = np.array([x_data1, x_data2])
        y_data1 = [1.0 / (1.0 + x * x) for x in x_data1]
        y_data2 = [1.0 / (2.0 + x * x) for x in x_data2]
        y_series = np.array([y_data1, y_data2], dtype=np.float64)
        search_args = tf.constant([[-1.2, 0.0, 0.3], [2.2, 1.8, 5.0]],
                                  dtype=tf.float64)

        spline2 = cubic.build_spline(x_series, y_series, dtype=tf.float32)
        msg = "Tensor conversion from float64 to float32 should fail here"
        with self.assertRaises(ValueError, msg=msg) as cm:
            self.evaluate(
                cubic.interpolate(search_args, spline2, dtype=tf.float32))
            print(cm)
예제 #8
0
    def test_compare_spline_32(self):
        x_data1 = np.linspace(-5.0, 5.0, num=11, dtype=np.float32)
        x_data2 = np.linspace(0.0, 10.0, num=11, dtype=np.float32)
        x_series = np.array([x_data1, x_data2])
        y_data1 = [1.0 / (1.0 + x * x) for x in x_data1]
        y_data2 = [1.0 / (2.0 + x * x) for x in x_data2]
        y_series = np.array([y_data1, y_data2], dtype=np.float32)
        search_args = tf.constant([[-1.2, 0.0, 0.3], [2.2, 1.8, 5.0]],
                                  dtype=tf.float32)

        spline2 = cubic.build_spline(x_series, y_series)
        result = tf.reshape(cubic.interpolate(search_args, spline2), [6])

        expected = tf.constant([
            0.401153371166, 1.0, 0.927547412565, 0.144129651521,
            0.194406085855, 0.037037037037
        ],
                               dtype=tf.float32)

        self.assertAllClose(expected, result)
예제 #9
0
    def test_build_and_interpolate(self):
        """Test a combined call by just calling interpolate."""
        # num splines = 2
        # spline_length = 11
        x_data1 = np.linspace(-5.0, 5.0, num=11)
        x_data2 = np.linspace(0.0, 10.0, num=11)
        x_series = np.array([x_data1, x_data2])
        y_data1 = [1.0 / (1.0 + x * x) for x in x_data1]
        y_data2 = [1.0 / (2.0 + x * x) for x in x_data2]
        y_series = np.array([y_data1, y_data2])

        # num_test_values = 3
        search_args = tf.constant([[-1.2, 0.0, 0.3], [2.2, 1.8, 5.0]],
                                  dtype=tf.float64)

        x_data_series = tf.stack(x_series, axis=0)
        y_data_series = tf.stack(y_series, axis=0)
        x_test = tf.stack(search_args, axis=0)

        spline = cubic.SplineParameters(x_data_series, y_data_series, None)

        predicted = cubic.interpolate(x_test, spline)

        self.assertAllEqual(tf.shape(x_test), tf.shape(predicted))
예제 #10
0
    def test_validate_args_interpolate(self):
        """Test that validation can be turned off in the interpolate call."""
        x_data1 = np.linspace(-5.0, 5.0, num=11)
        x_data2 = np.linspace(0.0, 10.0, num=11)
        x_series = np.array([x_data1, x_data2])
        y_data1 = [1.0 / (1.0 + x * x) for x in x_data1]
        y_data2 = [1.0 / (2.0 + x * x) for x in x_data2]
        y_series = np.array([y_data1, y_data2])
        x_data_series = tf.stack(x_series, axis=0)
        y_data_series = tf.stack(y_series, axis=0)

        # num_test_values = 3
        search_args = tf.constant([[-5.2, 0.0, 5.3], [2.2, 1.8, 5.0]],
                                  dtype=tf.float64)
        x_test = tf.stack(search_args, axis=0)
        spline = cubic.build_spline(x_data_series, y_data_series)

        # this should not fail with a validation error but a separate error
        # thrown by gather_nd
        msg = "The error should be an invalid argument"
        with self.assertRaises(tf.errors.InvalidArgumentError, msg=msg) as cm:
            self.evaluate(
                cubic.interpolate(x_test, spline, validate_args=False))
            print(cm.exception)