Как индексировать RaggedTensor вдоль рваного измерения в TensorFlow? - PullRequest
2 голосов
/ 27 марта 2019

Мне нужно получить значения в неровном тензоре путем индексации по неровному измерению.Некоторые операции индексации ([:, :x], [:, -x:] или [:, x:y]), но не прямая индексация ([:, x]):

R = tf.RaggedTensor.from_tensor([[1, 2, 3], [4, 5, 6]])
print(R[:, :2]) # RaggedTensor([[1, 2], [4, 5]])
print(R[:, 1:2]) # RaggedTensor([[2], [5]])
print(R[:, 1])  # ValueError: Cannot index into an inner ragged dimension.

Документация объясняет, почему это не удается:

RaggedTensors поддерживает многомерное индексирование и нарезку, с одним ограничением: индексация в неровное измерение не допускается.Этот случай проблематичен, поскольку указанное значение может существовать в одних строках, но не в других.В таких случаях не очевидно, должны ли мы (1) вызвать IndexError;(2) использовать значение по умолчанию;или (3) пропустить это значение и вернуть тензор с меньшим количеством строк, чем мы начали.Следуя руководящим принципам Python («Перед лицом неоднозначности откажитесь от соблазна гадать»), в настоящее время мы запрещаем эту операцию.

Это имеет смысл, но как мне на самом деле реализовать варианты 1,2 и 3?Должен ли я преобразовать рваный массив в массив тензоров Python и вручную перебирать их?Есть ли более эффективное решение?Тот, который будет работать на 100% в графе TensorFlow, без прохождения через интерпретатор Python?

1 Ответ

1 голос
/ 15 апреля 2019

Если у вас есть 2D RaggedTensor, то вы можете получить поведение (3) с помощью:

def get_column_slice_v3(rt, column):
  assert column >= 0  # Negative column index not supported
  slice = rt[:, column:column+1]
  return slice.flat_values

И вы можете получить поведение (1), добавив утверждение, что rt.nrows () == tf.size (slice.flat_values):

def get_column_slice_v1(rt, column):
  assert column >= 0  # Negative column index not supported
  slice = rt[:, column:column+1]
  with tf.assert_equal(rt.nrows(), tf.size(slice.flat_values):
    return tf.identity(slice.flat_values)

Чтобы получить поведение (2), я думаю, что самый простой способ - это, вероятно, объединить вектор значений по умолчанию, а затем снова нарезать:

def get_colum_slice_v2(rt, column, default=None):
  assert column >= 0  # Negative column index not supported
  slice = rt[:, column:column+1]
  if default is None:
    defaults = tf.zeros([slice.nrows(), 1], slice.dtype)
  ele:
    defaults = tf.fill([slice.nrows(), 1], default)
  slice_plus_default = tf.concat([rt, defaults], axis=1)
  slice2 = slice_plus_defaults[:1]
  return slice2.flat_values

Можно расширить их для поддержки многомерных рваных тензоров, но логика становится немного более сложной.Также должно быть возможно расширить их для поддержки отрицательных индексов столбцов.

...