message: Improves "SparseTensor labels are not supported" error message.
diff: @@ -188,9 +188,6 @@ class _Head(object):
  def _maybe_expand_dim(tensor):
  """Expand the dim of `tensor` with static rank 1."""
  with ops.name_scope(None, 'maybe_expand_dim', (tensor,)):
  - tensor = sparse_tensor.convert_to_tensor_or_sparse_tensor(tensor)
  - if isinstance(tensor, sparse_tensor.SparseTensor):
  - raise ValueError('SparseTensor labels are not supported.')
  static_shape = tensor.shape
  if static_shape is None:
  return tensor
  @@ -199,12 +196,21 @@ def _maybe_expand_dim(tensor):
  else tensor)
  -def _check_labels(labels, expected_labels_dimension):
  - """Check labels type and shape."""
  +def _check_and_reshape_dense_labels(labels, expected_labels_dimension):
  + """Checks dense labels type and shape and reshapes to 2D Tensor."""
  with ops.name_scope(None, 'labels', (labels,)) as scope:
  labels = sparse_tensor.convert_to_tensor_or_sparse_tensor(labels)
  if isinstance(labels, sparse_tensor.SparseTensor):
  - raise ValueError('SparseTensor labels are not supported.')
  + raise ValueError(
  + 'SparseTensor labels are not supported. '
  + 'labels must be a Tensor of shape [batch_size, %s]. '
  + 'Suggested Fix (1): Check the label feature in your data. '
  + 'Each example must contain %s value(s). If not, your choice of label '
  + 'was probably incorrect. '
  + 'Suggested Fix (2): In your input_fn, use '
  + 'tf.sparse_tensor_to_dense() to turn labels into a Tensor.'
  + '' % (expected_labels_dimension, expected_labels_dimension))
  + labels = _maybe_expand_dim(labels)
  labels_shape = array_ops.shape(labels)
  err_msg = 'labels shape must be [batch_size, {}]'.format(
  expected_labels_dimension)
  @@ -430,7 +436,7 @@ class _MultiClassHeadWithSoftmaxCrossEntropyLoss(_Head):
  def create_loss(self, features, mode, logits, labels):
  """See `Head`."""
  del mode, features # Unused for this head.
  - label_ids = self._label_ids(_check_labels(_maybe_expand_dim(labels), 1))
  + label_ids = self._label_ids(_check_and_reshape_dense_labels(labels, 1))
  unweighted_loss = losses.sparse_softmax_cross_entropy(
  labels=label_ids, logits=logits, reduction=losses.Reduction.NONE)
  # Restore the squeezed dim, so unweighted_loss matches the weights shape.
  @@ -674,7 +680,7 @@ class _BinaryLogisticHeadWithSigmoidCrossEntropyLoss(_Head):
  def create_loss(self, features, mode, logits, labels):
  """See `Head`."""
  del mode, features # Unused for this head.
  - labels = _check_labels(_maybe_expand_dim(labels), self.logits_dimension)
  + labels = _check_and_reshape_dense_labels(labels, self.logits_dimension)
  if self._label_vocabulary is not None:
  labels = lookup_ops.index_table_from_tensor(
  vocabulary_list=tuple(self._label_vocabulary),
  @@ -823,8 +829,8 @@ class _RegressionHeadWithMeanSquaredErrorLoss(_Head):
  def create_loss(self, features, mode, logits, labels):
  """See `Head`."""
  del mode, features # Unused for this head.
  - labels = _check_labels(
  - _maybe_expand_dim(math_ops.to_float(labels)), self._logits_dimension)
  + labels = _check_and_reshape_dense_labels(
  + math_ops.to_float(labels), self._logits_dimension)
  return LossAndLabels(
  unweighted_loss=losses.mean_squared_error(
  labels=labels, predictions=logits, reduction=losses.Reduction.NONE),
  