Форма данных: вещание, индексация и кодирование с рваными тенорами
29 июля 2025 г.Обзор контента
- Индексация
- Примеры индексации: 2 -й рваный тензор
- Примеры индексации: 3D рванный тензор
- Преобразование типа тензора
- Оценка рваных тензоров
- Рваные формы
- Статическая форма
- Динамическая форма
- Вещание
- Raggedtensor Кодирование
- Многочисленные рваные размеры
- Рваные звания и плоские значения
- Единообразные внутренние размеры
- Равномерные неинтересные измерения
Индексация
Руггенные тензоры поддерживают индексацию в стиле Python, включая многомерную индексацию и нарезку. Следующие примеры демонстрируют индексацию рваного тензора с 2D и 3D -рваным тензором.
Примеры индексации: 2 -й рваный тензор
queries = tf.ragged.constant(
[['Who', 'is', 'George', 'Washington'],
['What', 'is', 'the', 'weather', 'tomorrow'],
['Goodnight']])
print(queries[1]) # A single query
tf.Tensor([b'What' b'is' b'the' b'weather' b'tomorrow'], shape=(5,), dtype=string)
print(queries[1, 2]) # A single word
tf.Tensor(b'the', shape=(), dtype=string)
print(queries[1:]) # Everything but the first row
<tf.RaggedTensor [[b'What', b'is', b'the', b'weather', b'tomorrow'], [b'Goodnight']]><tf.RaggedTensor [[b'What', b'is', b'the', b'weather', b'tomorrow'], [b'Goodnight']]>
print(queries[:, :3]) # The first 3 words of each query
<tf.RaggedTensor [[b'Who', b'is', b'George'], [b'What', b'is', b'the'], [b'Goodnight']]>
print(queries[:, -2:]) # The last 2 words of each query
<tf.RaggedTensor [[b'George', b'Washington'], [b'weather', b'tomorrow'], [b'Goodnight']]>
Примеры индексации: 3D рванный тензор
rt = tf.ragged.constant([[[1, 2, 3], [4]],
[[5], [], [6]],
[[7]],
[[8, 9], [10]]])
print(rt[1]) # Second row (2D RaggedTensor)
<tf.RaggedTensor [[5], [], [6]]>
print(rt[3, 0]) # First element of fourth row (1D Tensor)
tf.Tensor([8 9], shape=(2,), dtype=int32)
print(rt[:, 1:3]) # Items 1-3 of each row (3D RaggedTensor)
<tf.RaggedTensor [[[4]], [[], [6]], [], [[10]]]>
print(rt[:, -1:]) # Last item of each row (3D RaggedTensor)
<tf.RaggedTensor [[[4]],
[[6]],
[[7]],
[[10]]]>
RaggedTensorS поддерживает многомерную индексацию и нарезку с одним ограничением: индексация в рваное измерение не допускается. Этот случай проблематичен, поскольку указанное значение может существовать в некоторых рядах, но не в других. В таких случаях не очевидно, следует ли вам (1) поднятьIndexError; (2) использовать значение по умолчанию; или (3) пропустите это значение и верните тензор с меньшим количеством рядов, чем вы начали. Послеруководящие принципы питона(«Перед лицом двусмысленности отказ от искушения угадать»), эта операция в настоящее время запрещена.
Преобразование типа тензора
АRaggedTensorКласс определяет методы, которые можно использовать для преобразования междуRaggedTensorпесокtf.Tensors илиtf.SparseTensors:
ragged_sentences = tf.ragged.constant([
['Hi'], ['Welcome', 'to', 'the', 'fair'], ['Have', 'fun']])
# RaggedTensor -> Tensor
print(ragged_sentences.to_tensor(default_value='', shape=[None, 10]))
tf.Tensor(
[[b'Hi' b'' b'' b'' b'' b'' b'' b'' b'' b'']
[b'Welcome' b'to' b'the' b'fair' b'' b'' b'' b'' b'' b'']
[b'Have' b'fun' b'' b'' b'' b'' b'' b'' b'' b'']], shape=(3, 10), dtype=string)
# Tensor -> RaggedTensor
x = [[1, 3, -1, -1], [2, -1, -1, -1], [4, 5, 8, 9]]
print(tf.RaggedTensor.from_tensor(x, padding=-1))
<tf.RaggedTensor [[1, 3], [2], [4, 5, 8, 9]]>
#RaggedTensor -> SparseTensor
print(ragged_sentences.to_sparse())
SparseTensor(indices=tf.Tensor(
[[0 0]
[1 0]
[1 1]
[1 2]
[1 3]
[2 0]
[2 1]], shape=(7, 2), dtype=int64), values=tf.Tensor([b'Hi' b'Welcome' b'to' b'the' b'fair' b'Have' b'fun'], shape=(7,), dtype=string), dense_shape=tf.Tensor([3 4], shape=(2,), dtype=int64))
# SparseTensor -> RaggedTensor
st = tf.SparseTensor(indices=[[0, 0], [2, 0], [2, 1]],
values=['a', 'b', 'c'],
dense_shape=[3, 3])
print(tf.RaggedTensor.from_sparse(st))
<tf.RaggedTensor [[b'a'], [], [b'b', b'c']]>
Оценка рваных тензоров
Чтобы получить доступ к значениям в рваном тензоре, вы можете:
- Использовать
tf.RaggedTensor.to_listЧтобы преобразовать рваный тензор в вложенный список Python. - Использовать
tf.RaggedTensor.numpyПреобразовать рваный тензор в массив Numpy, ценности которых являются вложенными массивами Numpy. - Разложить рваный тензор в свои компоненты, используя
tf.RaggedTensor.valuesиtf.RaggedTensor.row_splitsсвойства или методы участия в строке, такие какtf.RaggedTensor.row_lengthsиtf.RaggedTensor.value_rowidsПолем - Используйте индексацию Python, чтобы выбрать значения из рваного тензора.
rt = tf.ragged.constant([[1, 2], [3, 4, 5], [6], [], [7]])
print("Python list:", rt.to_list())
print("NumPy array:", rt.numpy())
print("Values:", rt.values.numpy())
print("Splits:", rt.row_splits.numpy())
print("Indexed value:", rt[1].numpy())
Python list: [[1, 2], [3, 4, 5], [6], [], [7]]
NumPy array: [array([1, 2], dtype=int32) array([3, 4, 5], dtype=int32)
array([6], dtype=int32) array([], dtype=int32) array([7], dtype=int32)]
Values: [1 2 3 4 5 6 7]
Splits: [0 2 5 6 6 7]
Indexed value: [3 4 5]
Рваные формы
Форма тензора указывает размер каждой оси. Например, форма[[1, 2], [3, 4], [5, 6]]является[3, 2], поскольку есть 3 ряда и 2 столбца. Tensorflow имеет два отдельных, но связанных способа для описания форм:
- статическая форма: Информация о размерах оси, которая известна статически (например, при отслеживании
tf.function) Может быть частично указан. - динамическая форма: Информация о времени выполнения о размерах оси.
Статическая форма
Статическая форма тензора содержит информацию о размерах оси, которая известна во время строительства графа. Для обоихtf.Tensorиtf.RaggedTensor, он доступен с помощью.shapeсвойство и кодируется с помощьюtf.TensorShape:
x = tf.constant([[1, 2], [3, 4], [5, 6]])
x.shape # shape of a tf.tensor
TensorShape([3, 2])
rt = tf.ragged.constant([[1], [2, 3], [], [4]])
rt.shape # shape of a tf.RaggedTensor
TensorShape([4, None])
Статическая форма рваного измерения всегдаNone(т.е. не указано). Однако обратное неправда - еслиTensorShapeизмерение естьNone, тогда это может указывать на то, что измерение оборван,илиЭто может указывать на то, что измерение равномерно, но его размер не известен.
Динамическая форма
Динамическая форма тензора содержит информацию о размерах оси, которая известна при запуске графика. Он построен с использованиемtf.shapeоперация Дляtf.TensorВtf.shapeВозвращает форму как 1D Целое числоTensor, гдеtf.shape(x)[i]размер осиiПолем
x = tf.constant([['a', 'b'], ['c', 'd'], ['e', 'f']])
tf.shape(x)
<tf.Tensor: shape=(2,), dtype=int32, numpy=array([3, 2], dtype=int32)>
Однако 1dTensorнедостаточно выразительна, чтобы описать формуtf.RaggedTensorПолем Вместо этого динамическая форма для рваных тензоров кодируется с использованием выделенного типа,tf.experimental.DynamicRaggedShapeПолем В следующем примереDynamicRaggedShapeвернулсяtf.shape(rt)Указывает, что рваный тензор имеет 4 ряда, с длиной 1, 3, 0 и 2:
rt = tf.ragged.constant([[1], [2, 3, 4], [], [5, 6]])
rt_shape = tf.shape(rt)
print(rt_shape)
<DynamicRaggedShape lengths=[4, (1, 3, 0, 2)] num_row_partitions=1>
Динамическая форма: операции
DynamicRaggedShapeS может использоваться с большинством Tensorflow Ops, которые ожидают формы, включаяtf.reshapeВtf.zerosВtf.onesПолемtf.fillВtf.broadcast_dynamic_shape, иtf.broadcast_toПолем
print(f"tf.reshape(x, rt_shape) = {tf.reshape(x, rt_shape)}")
print(f"tf.zeros(rt_shape) = {tf.zeros(rt_shape)}")
print(f"tf.ones(rt_shape) = {tf.ones(rt_shape)}")
print(f"tf.fill(rt_shape, 9) = {tf.fill(rt_shape, 'x')}")
tf.reshape(x, rt_shape) = <tf.RaggedTensor [[b'a'], [b'b', b'c', b'd'], [], [b'e', b'f']]>
tf.zeros(rt_shape) = <tf.RaggedTensor [[0.0], [0.0, 0.0, 0.0], [], [0.0, 0.0]]>
tf.ones(rt_shape) = <tf.RaggedTensor [[1.0], [1.0, 1.0, 1.0], [], [1.0, 1.0]]>
tf.fill(rt_shape, 9) = <tf.RaggedTensor [[b'x'], [b'x', b'x', b'x'], [], [b'x', b'x']]>
Динамическая форма: индексация и нарезка
DynamicRaggedShapeМожно также быть проиндексирован, чтобы получить размеры равномерных размеров. Например, мы можем найти количество рядов в рваном Тенсоре, используяtf.shape(rt)[0](Как и для нерагированного тензора):
rt_shape[0]
<tf.Tensor: shape=(), dtype=int32, numpy=4>
Тем не менее, это ошибка использования индексации, чтобы попытаться получить размер рваного измерения, поскольку у нее нет одного размера. (СRaggedTensorотслеживает, какие оси уморожены, эта ошибка бросается только во время энергичного выполнения или при отслеживанииtf.function; Он никогда не будет брошен при выполнении конкретной функции.)
try:
rt_shape[1]
except ValueError as e:
print("Got expected ValueError:", e)
Got expected ValueError: Index 1 is not uniform
DynamicRaggedShapeS также может быть нарезан, пока срез либо начинается с оси0, или содержит только плотные размеры.
rt_shape[:1]
<DynamicRaggedShape lengths=[4] num_row_partitions=0>
Динамическая форма: кодирование
DynamicRaggedShapeкодируется с использованием двух полей:
inner_shape: Целочисленный вектор, дающий форму плотногоtf.TensorПолемrow_partitions: Списокtf.experimental.RowPartitionОбъекты, описывающие, как наиболее внешнее измерение этой внутренней формы должно быть разделено, чтобы добавить рваные оси.
Для получения дополнительной информации о разделах строк см. В разделе «Raggedtensor Coding» ниже, а также документы API дляtf.experimental.RowPartitionПолем
Динамическая форма: конструкция
DynamicRaggedShapeчаще всего строится путем примененияtf.shapeвRaggedTensor, но это также может быть построено напрямую:
tf.experimental.DynamicRaggedShape(
row_partitions=[tf.experimental.RowPartition.from_row_lengths([5, 3, 2])],
inner_shape=[10, 8])
<DynamicRaggedShape lengths=[3, (5, 3, 2), 8] num_row_partitions=1>
Если длина всех рядов известна статически,DynamicRaggedShape.from_lengthsТакже можно использовать для построения динамической рваной формы. (Это в основном полезно для тестирования и демонстрационного кода, так как редко можно известно длина рваных измерений статически).
tf.experimental.DynamicRaggedShape.from_lengths([4, (2, 1, 0, 8), 12])
<DynamicRaggedShape lengths=[4, (2, 1, 0, 8), 12] num_row_partitions=1>
Вещание
Вещание - это процесс создания тензоров с различными формами, которые имеют совместимые формы для ElementWise Operations. Для получения дополнительной информации о вещании см.
- Numpy: вещание
tf.broadcast_dynamic_shapetf.broadcast_to
Основные шаги для трансляции двух входовxиyиметь совместимые формы:
- Если
xиyНе иметь одинакового количества размеров, затем добавьте внешние размеры (с размером 1), пока они не сделают. - Для каждого измерения, где
xиyиметь разные размеры:
- Если
xилиyиметь размер1в измеренииd, затем повторите его значения по всему измерениюdЧтобы соответствовать размеру другого ввода. - В противном случае поднимите исключение (
xиyне совместимы).
Где размер тензора в равномерном измерении представляет собой одно число (размер ломтиков по этому измерению); И размер тензора в рваном измерении представляет собой список длины среза (для всех срезов по всему измерению).
Примеры вещания
# x (2D ragged): 2 x (num_rows)
# y (scalar)
# result (2D ragged): 2 x (num_rows)
x = tf.ragged.constant([[1, 2], [3]])
y = 3
print(x + y)
<tf.RaggedTensor [[4, 5], [6]]>
# x (2d ragged): 3 x (num_rows)
# y (2d tensor): 3 x 1
# Result (2d ragged): 3 x (num_rows)
x = tf.ragged.constant(
[[10, 87, 12],
[19, 53],
[12, 32]])
y = [[1000], [2000], [3000]]
print(x + y)
<tf.RaggedTensor [[1010, 1087, 1012], [2019, 2053], [3012, 3032]]>
# x (3d ragged): 2 x (r1) x 2
# y (2d ragged): 1 x 1
# Result (3d ragged): 2 x (r1) x 2
x = tf.ragged.constant(
[[[1, 2], [3, 4], [5, 6]],
[[7, 8]]],
ragged_rank=1)
y = tf.constant([[10]])
print(x + y)
<tf.RaggedTensor [[[11, 12],
[13, 14],
[15, 16]], [[17, 18]]]>
# x (3d ragged): 2 x (r1) x (r2) x 1
# y (1d tensor): 3
# Result (3d ragged): 2 x (r1) x (r2) x 3
x = tf.ragged.constant(
[
[
[[1], [2]],
[],
[[3]],
[[4]],
],
[
[[5], [6]],
[[7]]
]
],
ragged_rank=2)
y = tf.constant([10, 20, 30])
print(x + y)
<tf.RaggedTensor [[[[11, 21, 31],
[12, 22, 32]], [], [[13, 23, 33]], [[14, 24, 34]]],
[[[15, 25, 35],
[16, 26, 36]], [[17, 27, 37]]]]>
Вот несколько примеров форм, которые не транслируются:
# x (2d ragged): 3 x (r1)
# y (2d tensor): 3 x 4 # trailing dimensions do not match
x = tf.ragged.constant([[1, 2], [3, 4, 5, 6], [7]])
y = tf.constant([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
try:
x + y
except tf.errors.InvalidArgumentError as exception:
print(exception)
Condition x == y did not hold.
Indices of first 3 different values:
[[1]
[2]
[3]]
Corresponding x values:
[ 4 8 12]
Corresponding y values:
[2 6 7]
First 3 elements of x:
[0 4 8]
First 3 elements of y:
[0 2 6]
# x (2d ragged): 3 x (r1)
# y (2d ragged): 3 x (r2) # ragged dimensions do not match.
x = tf.ragged.constant([[1, 2, 3], [4], [5, 6]])
y = tf.ragged.constant([[10, 20], [30, 40], [50]])
try:
x + y
except tf.errors.InvalidArgumentError as exception:
print(exception)
Condition x == y did not hold.
Indices of first 2 different values:
[[1]
[3]]
Corresponding x values:
[3 6]
Corresponding y values:
[2 5]
First 3 elements of x:
[0 3 4]
First 3 elements of y:
[0 2 4]
# x (3d ragged): 3 x (r1) x 2
# y (3d ragged): 3 x (r1) x 3 # trailing dimensions do not match
x = tf.ragged.constant([[[1, 2], [3, 4], [5, 6]],
[[7, 8], [9, 10]]])
y = tf.ragged.constant([[[1, 2, 0], [3, 4, 0], [5, 6, 0]],
[[7, 8, 0], [9, 10, 0]]])
try:
x + y
except tf.errors.InvalidArgumentError as exception:
print(exception)
Condition x == y did not hold.
Indices of first 3 different values:
[[1]
[2]
[3]]
Corresponding x values:
[2 4 6]
Corresponding y values:
[3 6 9]
First 3 elements of x:
[0 2 4]
First 3 elements of y:
[0 3 6]
Raggedtensor Кодирование
Рваные тензоры кодируются с использованиемRaggedTensorсорт. Внутренне каждыйRaggedTensorсостоит из:
- А
valuesТенсор, который объединяет ряды с переменной длиной в сплющенном списке. - А
row_partition, что указывает на то, как эти сплющенные значения делятся на ряды.

Аrow_partitionможно хранить с помощью четырех разных кодировки:
row_splitsявляется целочисленным вектором, указывающим точки разделения между рядами.value_rowidsэто целочисленный вектор, указывающий индекс строки для каждого значения.row_lengthsэто целочисленный вектор, указывающий длину каждой строки.uniform_row_lengthэто целочисленный скаляр, указывающий одну длину для всех рядов.

Целочисленный скалярnrowsтакже может быть включен вrow_partitionкодирование для учета пустых строк с запеканием сvalue_rowidsили пустые ряды сuniform_row_lengthПолем
rt = tf.RaggedTensor.from_row_splits(
values=[3, 1, 4, 1, 5, 9, 2],
row_splits=[0, 4, 4, 6, 7])
print(rt)
<tf.RaggedTensor [[3, 1, 4, 1], [], [5, 9], [2]]>
Выбор того, какой кодирование для использования для разделов строк управляется внутренне рваными тензорами для повышения эффективности в некоторых контекстах. В частности, некоторые из преимуществ и недостатков различных схем, связанных с участием строк:
- Эффективная индексация:
row_splitsКодирование позволяет индексировать постоянное время и нарезать на рваные тензоры. - Эффективная конкатенация:
row_lengthsКодирование более эффективно при сознании рваных тензоров, поскольку длина строк не меняется, когда два тензора объединяются вместе. - Маленький размер кодирования:
value_rowidsКодирование более эффективно при хранении рваных тензоров, которые имеют большое количество пустых рядов, поскольку размер тензора зависит только от общего количества значений. С другой стороны,row_splitsиrow_lengthsКодирования более эффективны при хранении рваных тензоров с более длинными рядами, поскольку им требуется только одно скалярное значение для каждой строки. - Совместимость:
value_rowidsСхема соответствуетсегментацияформат, используемый операциями, напримерtf.segment_sumПолем Аrow_limitsсхема соответствует формату, используемому OP, такими какtf.sequence_maskПолем - Равномерные размеры: Как обсуждалось ниже,
uniform_row_lengthКодирование используется для кодирования рваных тензоров с однородными размерами.
Многочисленные рваные размеры
Рваный тензор с несколькими рваными размерами кодируется с использованием вложенногоRaggedTensorдляvaluesтензор. Каждый вложенRaggedTensorДобавляет одно рваное измерение.

rt = tf.RaggedTensor.from_row_splits(
values=tf.RaggedTensor.from_row_splits(
values=[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
row_splits=[0, 3, 3, 5, 9, 10]),
row_splits=[0, 1, 1, 5])
print(rt)
print("Shape: {}".format(rt.shape))
print("Number of partitioned dimensions: {}".format(rt.ragged_rank))
<tf.RaggedTensor [[[10, 11, 12]], [], [[], [13, 14], [15, 16, 17, 18], [19]]]>
Shape: (3, None, None)
Number of partitioned dimensions: 2
Функциональная функцияtf.RaggedTensor.from_nested_row_splitsможет быть использован для построения рваного денсора с несколькими рваными размерами непосредственно путем предоставления спискаrow_splitsТенсоры:
rt = tf.RaggedTensor.from_nested_row_splits(
flat_values=[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
nested_row_splits=([0, 1, 1, 5], [0, 3, 3, 5, 9, 10]))
print(rt)
<tf.RaggedTensor [[[10, 11, 12]], [], [[], [13, 14], [15, 16, 17, 18], [19]]]>
Рваные звания и плоские значения
Рваный тензоррваное званиеэто количество раз, что базовыйvaluesтензор был разделен (то есть глубина гнездованияRaggedTensorобъекты). Внутреннийvaluesтензор известен как егоflat_valuesПолем В следующем примере,conversationsимеет Ragged_rank = 3, и егоflat_values1dTensorс 24 струнами:
# shape = [batch, (paragraph), (sentence), (word)]
conversations = tf.ragged.constant(
[[[["I", "like", "ragged", "tensors."]],
[["Oh", "yeah?"], ["What", "can", "you", "use", "them", "for?"]],
[["Processing", "variable", "length", "data!"]]],
[[["I", "like", "cheese."], ["Do", "you?"]],
[["Yes."], ["I", "do."]]]])
conversations.shape
TensorShape([2, None, None, None])
assert conversations.ragged_rank == len(conversations.nested_row_splits)
conversations.ragged_rank # Number of partitioned dimensions.
3
conversations.flat_values.numpy()
array([b'I', b'like', b'ragged', b'tensors.', b'Oh', b'yeah?', b'What',
b'can', b'you', b'use', b'them', b'for?', b'Processing',
b'variable', b'length', b'data!', b'I', b'like', b'cheese.', b'Do',
b'you?', b'Yes.', b'I', b'do.'], dtype=object)
Единообразные внутренние размеры
Рваные тензоры с равномерными внутренними размерами кодируются с использованием многомерногоtf.Tensorдля flat_values (т.е.values)

rt = tf.RaggedTensor.from_row_splits(
values=[[1, 3], [0, 0], [1, 3], [5, 3], [3, 3], [1, 2]],
row_splits=[0, 3, 4, 6])
print(rt)
print("Shape: {}".format(rt.shape))
print("Number of partitioned dimensions: {}".format(rt.ragged_rank))
print("Flat values shape: {}".format(rt.flat_values.shape))
print("Flat values:\n{}".format(rt.flat_values))
<tf.RaggedTensor [[[1, 3],
[0, 0],
[1, 3]], [[5, 3]], [[3, 3],
[1, 2]]]>
Shape: (3, None, 2)
Number of partitioned dimensions: 1
Flat values shape: (6, 2)
Flat values:
[[1 3]
[0 0]
[1 3]
[5 3]
[3 3]
[1 2]]
Равномерные неинтересные измерения
Рваные тензоры с равномерными неинтересными измерениями кодируются распределительными рядами сuniform_row_lengthПолем

rt = tf.RaggedTensor.from_uniform_row_length(
values=tf.RaggedTensor.from_row_splits(
values=[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
row_splits=[0, 3, 5, 9, 10]),
uniform_row_length=2)
print(rt)
print("Shape: {}".format(rt.shape))
print("Number of partitioned dimensions: {}".format(rt.ragged_rank))
<tf.RaggedTensor [[[10, 11, 12], [13, 14]],
[[15, 16, 17, 18], [19]]]>
Shape: (2, 2, None)
Number of partitioned dimensions: 2
Первоначально опубликовано на
Оригинал