class_docstr: Posterior predictive in a conjugate Multi-task GP regression model.
code: def _check_observations_valid(self, observations):
      observation_rank = tensorshape_util.rank(observations.shape)
  
      if observation_rank is None:
          return
  
      if observation_rank >= 1:
          # Check that the last dimension of observations matches the number of
          # tasks.
          num_observations = tf.compat.dimension_value(
              observations.shape[-1]
          )
          if (
              num_observations is not None
              and num_observations != 1
              and num_observations != self.kernel.num_tasks
          ):
              raise ValueError(
                  f"Expected the number of observations {num_observations} "
                  f"to broadcast / match the number of tasks "
                  f"{self.kernel.num_tasks}"
              )
  
      if observation_rank >= 2:
          num_index_points = tf.compat.dimension_value(
              observations.shape[-2]
          )
  
          flat_shapes = tf.nest.flatten(
              tf.nest.map_structure(
                  lambda t, nd: t.shape[-(nd + 1) : -nd],
                  self.observation_index_points,
                  self.kernel.feature_ndims,
              )
          )
          if None in flat_shapes:
              expected_num_index_points = None
          else:
              dim = functools.reduce(
                  tf.broadcast_static_shape,
                  flat_shapes,
                  tf.TensorShape([]),
              )
              expected_num_index_points = tf.compat.dimension_value(
                  dim[0]
              )
  
          if (
              num_index_points is not None
              and expected_num_index_points is not None
              and num_index_points != 1
              and num_index_points != expected_num_index_points
          ):
              raise ValueError(
                  f"Expected number of observation index points "
                  f"{expected_num_index_points} to broadcast / match the second "
                  f"to last dimension of `observations` {num_index_points}"
              )
  
imports: import functools
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import softplus
  from tensorflow_probability.python.distributions import cholesky_util
  from tensorflow_probability.python.distributions import distribution
  from tensorflow_probability.python.distributions import mvn_linear_operator
  from tensorflow_probability.python.distributions.internal import stochastic_process_util
  from tensorflow_probability.python.experimental.distributions import multitask_gaussian_process
  from tensorflow_probability.python.experimental.linalg import linear_operator_unitary
  from tensorflow_probability.python.experimental.psd_kernels import multitask_kernel
  from tensorflow_probability.python.internal import batch_shape_lib
  from tensorflow_probability.python.internal import distribution_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import nest_util
  from tensorflow_probability.python.internal import parameter_properties
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import reparameterization
  from tensorflow_probability.python.internal import tensor_util
  from tensorflow_probability.python.internal import tensorshape_util
  from tensorflow_probability.python.math.psd_kernels.internal import util
label_desc: Use image node_id 2 for calling the MultiTaskGaussianProcessRegressionModel obj's underlying member method code with example usage: obj._check_observations_valid(observations) without return types