class_docstr: Performs interpolation in a 2-dimensional space.
  
  For input `x_data` in x-direction we assume that values in y-direction are
  given by `y_data` and the corresponding function values by `z_data`.
  For given `x` and `y` along x- and y- direction respectively,
  the interpolated function values are computed on grid `[x, y]`.
  The interpolation is first performed along y-direction for every `x_data`
  point and all `y` using 1-d cubic spline interpolation. Next, for
  each interpolated `y_value` point, the function values are interpolated along
  x-direction for `x` using 1-d cubic spline interpolation.
  Constant extrapolation is used for the linear interpolation and natural
  boundary conditions are used for the cubic spline.
  
  ### Example. Volatility surface interpolation
  
  ```python
  dtype = np.float64
  times = tf.constant([2., 2.5, 3, 4.5], dtype=dtype)
  strikes = tf.constant([16, 22, 35], dtype=dtype)
  
  times_data = tf.constant([1.5, 2.5, 3.5, 4.5, 5.5], dtype=dtype)
  # Corresponding squared volatility values
  sigma_square_data = tf.constant(
      [[0.15, 0.25, 0.35, 0.4, 0.45, 0.4],
       [0.2, 0.35, 0.55, 0.45, 0.4, 0.6],
       [0.3, 0.45, 0.25, 0.4, 0.5, 0.65],
       [0.25, 0.25, 0.45, 0.25, 0.5, 0.55],
       [0.35, 0.35, 0.25, 0.4, 0.55, 0.65]], dtype=dtype)
  # Interpolation is done for the total variance
  total_variance = tf.expand_dims(times_data, -1) * sigma_square_data
  # Corresponding strike values. Notice we need to broadcast to the shape of
  # `sigma_square_data`
  strike_data = tf.broadcast_to(
      tf.constant([15, 25, 35, 40, 50, 55], dtype=dtype), [5, 6])
  # Interpolate total variance on for coordinates `(times, strikes)`
  interpolator = Interpolation2D(times_data, strike_data, total_variance,
                                 dtype=dtype)
  interpolated_values = interpolator.interpolate(times, strikes)
  ```
docstr: Initialize the 2d-interpolation object.
  
  Args:
    x_data: A `Tensor` of real `dtype` and shape
      `batch_shape + [num_x_data_points]`.
      Defines the x-coordinates of the input data. `num_x_data_points` should
      be >= 2. The elements of `x_data` should be in a non-decreasing order.
    y_data: A `Tensor` of the same `dtype` as `x_data` and shape
      `batch_shape + [num_x_data_points, num_y_data_points]`. Defines the
      y-coordinates of the input data. `num_y_data_points` should be >= 2.
      The elements of `y_data` should be in a non-decreasing order along last
      dimension.
    z_data: A `Tensor` of the same shape and `dtype` as `y_data`. Defines the
      z-coordinates of the input data (i.e., the function values).
    dtype: Optional dtype for the input `Tensor`s.
      Default value: `None` which maps to the default dtype inferred by
      TensorFlow.
    name: Python `str` name prefixed to ops created by this class.
      Default value: `None` which is mapped to the default name
      `interpolation_2d`.
docstr_tok: ["Initialize","the","2d-interpolation","object",".","Args",":","x_data",":","A","`","Tensor","`","of","real","`","dtype","`","and","shape","`","batch_shape","+","[","num_x_data_points","]","`",".","Defines","the","x-coordinates","of","the","input","data",".","`","num_x_data_points","`","should","be",">","=","2",".","The","elements","of","`","x_data","`","should","be","in","a","non-decreasing","order",".","y_data",":","A","`","Tensor","`","of","the","same","`","dtype","`","as","`","x_data","`","and","shape","`","batch_shape","+","[","num_x_data_points",",","num_y_data_points","]","`",".","Defines","the","y-coordinates","of","the","input","data",".","`","num_y_data_points","`","should","be",">","=","2",".","The","elements","of","`","y_data","`","should","be","in","a","non-decreasing","order","along","last","dimension",".","z_data",":","A","`","Tensor","`","of","the","same","shape","and","`","dtype","`","as","`","y_data","`",".","Defines","the","z-coordinates","of","the","input","data","(","i.e.",",","the","function","values",")",".","dtype",":","Optional","dtype","for","the","input","`","Tensor","`","s",".","Default","value",":","`","None","`","which","maps","to","the","default","dtype","inferred","by","TensorFlow",".","name",":","Python","`","str","`","name","prefixed","to","ops","created","by","this","class",".","Default","value",":","`","None","`","which","is","mapped","to","the","default","name","`","interpolation_2d","`","."]
code: def __init__(
      self,
      x_data: types.RealTensor,
      y_data: types.RealTensor,
      z_data: types.RealTensor,
      dtype: tf.DType = None,
      name: str = None,
  ):
      """Initialize the 2d-interpolation object.
  
      Args:
        x_data: A `Tensor` of real `dtype` and shape
          `batch_shape + [num_x_data_points]`.
          Defines the x-coordinates of the input data. `num_x_data_points` should
          be >= 2. The elements of `x_data` should be in a non-decreasing order.
        y_data: A `Tensor` of the same `dtype` as `x_data` and shape
          `batch_shape + [num_x_data_points, num_y_data_points]`. Defines the
          y-coordinates of the input data. `num_y_data_points` should be >= 2.
          The elements of `y_data` should be in a non-decreasing order along last
          dimension.
        z_data: A `Tensor` of the same shape and `dtype` as `y_data`. Defines the
          z-coordinates of the input data (i.e., the function values).
        dtype: Optional dtype for the input `Tensor`s.
          Default value: `None` which maps to the default dtype inferred by
          TensorFlow.
        name: Python `str` name prefixed to ops created by this class.
          Default value: `None` which is mapped to the default name
          `interpolation_2d`.
      """
  
      name = name or "interpolation_2d"
      with tf.name_scope(name):
          self._xdata = tf.convert_to_tensor(
              x_data, dtype=dtype, name="x_data"
          )
          self._dtype = dtype or self._xdata.dtype
          self._ydata = tf.convert_to_tensor(
              y_data, dtype=self._dtype, name="y_data"
          )
          self._zdata = tf.convert_to_tensor(
              z_data, dtype=self._dtype, name="z_data"
          )
          self._name = name
  
          # For each `x_data` point, build a spline in y-direction
          self._spline_yz = cubic.build_spline(
              self._ydata, self._zdata, name="spline_y_direction"
          )
  
imports: import tensorflow.compat.v2
  from tf_quant_finance import types
  from tf_quant_finance.math.interpolation import cubic
  from tf_quant_finance.math.interpolation import linear
label_desc: Use image node_id 1 to create a new Interpolation2D object  with example: obj = Interpolation2D(x_data, y_data, z_data, dtype, name)