Zerlumpte Tensoren

Auf TensorFlow.org ansehen Quelle auf GitHub anzeigenNotizbuch herunterladen

API - Dokumentation: tf.RaggedTensor tf.ragged

Aufstellen

import math
import tensorflow as tf

Überblick

Ihre Daten haben viele Formen; deine Tensoren sollten das auch. Ragged Tensoren sind die TensorFlow Äquivalent nested variabler Länge Listen. Sie erleichtern das Speichern und Verarbeiten von Daten mit ungleichmäßigen Formen, einschließlich:

  • Features mit variabler Länge, z. B. die Anzahl der Schauspieler in einem Film.
  • Stapel von sequenziellen Eingaben mit variabler Länge, z. B. Sätze oder Videoclips.
  • Hierarchische Eingaben wie Textdokumente, die in Abschnitte, Absätze, Sätze und Wörter unterteilt sind.
  • Einzelne Felder in strukturierten Eingaben, wie z. B. Protokollpuffer.

Was Sie mit einem zerlumpten Tensor machen können

Ragged Tensoren werden von mehr als hundert TensorFlow Operationen, einschließlich der mathematischen Operationen (wie beispielsweise unterstützte tf.add und tf.reduce_mean ), array (wie tf.concat und tf.tile ), Fadenmanipulation ops (wie tf.substr ), Strömungssteueroperationen (wie tf.while_loop und tf.map_fn ), und viele andere:

digits = tf.ragged.constant([[3, 1, 4, 1], [], [5, 9, 2], [6], []])
words = tf.ragged.constant([["So", "long"], ["thanks", "for", "all", "the", "fish"]])
print(tf.add(digits, 3))
print(tf.reduce_mean(digits, axis=1))
print(tf.concat([digits, [[5, 3]]], axis=0))
print(tf.tile(digits, [1, 2]))
print(tf.strings.substr(words, 0, 2))
print(tf.map_fn(tf.math.square, digits))
<tf.RaggedTensor [[6, 4, 7, 4], [], [8, 12, 5], [9], []]>
tf.Tensor([2.25              nan 5.33333333 6.                nan], shape=(5,), dtype=float64)
<tf.RaggedTensor [[3, 1, 4, 1], [], [5, 9, 2], [6], [], [5, 3]]>
<tf.RaggedTensor [[3, 1, 4, 1, 3, 1, 4, 1], [], [5, 9, 2, 5, 9, 2], [6, 6], []]>
<tf.RaggedTensor [[b'So', b'lo'], [b'th', b'fo', b'al', b'th', b'fi']]>
<tf.RaggedTensor [[9, 1, 16, 1], [], [25, 81, 4], [36], []]>

Es gibt auch eine Reihe von Methoden und Operationen, die spezifisch für Ragged Tensors sind, einschließlich Factory-Methoden, Konvertierungsmethoden und Value-Mapping-Operationen. Eine Liste der unterstützten Ops finden Sie in der tf.ragged Paketdokumentation.

Ragged Tensoren werden von vielen TensorFlow APIs unterstützt, einschließlich Keras , Datensätze , tf.function , SavedModels und tf.Example . Weitere Informationen finden Sie unter dem Abschnitt über TensorFlow APIs.

Wie bei normalen Tensoren können Sie die Indexierung im Python-Stil verwenden, um auf bestimmte Slices eines zerlumpten Tensors zuzugreifen. Weitere Informationen finden Sie im Abschnitt weiter unten auf Indizierung.

print(digits[0])       # First row
tf.Tensor([3 1 4 1], shape=(4,), dtype=int32)
print(digits[:, :2])   # First two values in each row.
<tf.RaggedTensor [[3, 1], [], [5, 9], [6], []]>
print(digits[:, -2:])  # Last two values in each row.
<tf.RaggedTensor [[4, 1], [], [9, 2], [6], []]>

Und genau wie normale Tensoren können Sie mit Python-Arithmetik- und Vergleichsoperatoren elementweise Operationen ausführen. Weitere Informationen finden Sie im Abschnitt über die Überladene Operatoren unten.

print(digits + 3)
<tf.RaggedTensor [[6, 4, 7, 4], [], [8, 12, 5], [9], []]>
print(digits + tf.ragged.constant([[1, 2, 3, 4], [], [5, 6, 7], [8], []]))
<tf.RaggedTensor [[4, 3, 7, 5], [], [10, 15, 9], [14], []]>

Wenn Sie eine Transformation auf die element Werten eines ausführen müssen RaggedTensor , können Sie tf.ragged.map_flat_values , die eine Funktion plus ein oder mehr Argumente verwendet , und wendet die Funktion des zu transformieren RaggedTensor ‚s Werte.

times_two_plus_one = lambda x: x * 2 + 1
print(tf.ragged.map_flat_values(times_two_plus_one, digits))
<tf.RaggedTensor [[7, 3, 9, 3], [], [11, 19, 5], [13], []]>

Ragged Tensoren können verschachtelten Python umgewandelt werden list s und NumPy array s:

digits.to_list()
[[3, 1, 4, 1], [], [5, 9, 2], [6], []]
digits.numpy()
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/ragged/ragged_tensor.py:2063: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
  return np.array(rows)
array([array([3, 1, 4, 1], dtype=int32), array([], dtype=int32),
       array([5, 9, 2], dtype=int32), array([6], dtype=int32),
       array([], dtype=int32)], dtype=object)

Konstruieren eines zerlumpten Tensors

Der einfachste Weg , ein ragged Tensor verwendet zu konstruieren tf.ragged.constant , die die baut RaggedTensor entsprechend einer gegebenen verschachtelt Python list oder NumPy array :

sentences = tf.ragged.constant([
    ["Let's", "build", "some", "ragged", "tensors", "!"],
    ["We", "can", "use", "tf.ragged.constant", "."]])
print(sentences)
<tf.RaggedTensor [[b"Let's", b'build', b'some', b'ragged', b'tensors', b'!'], [b'We', b'can', b'use', b'tf.ragged.constant', b'.']]>
paragraphs = tf.ragged.constant([
    [['I', 'have', 'a', 'cat'], ['His', 'name', 'is', 'Mat']],
    [['Do', 'you', 'want', 'to', 'come', 'visit'], ["I'm", 'free', 'tomorrow']],
])
print(paragraphs)
<tf.RaggedTensor [[[b'I', b'have', b'a', b'cat'], [b'His', b'name', b'is', b'Mat']], [[b'Do', b'you', b'want', b'to', b'come', b'visit'], [b"I'm", b'free', b'tomorrow']]]>

Ragged Tensoren können auch durch Paarung flache Werte Tensoren mit Zeilen Partitionieren Tensoren der angibt , wie die Werte , konstruiert werden sollte in Reihen unterteilt werden, Fabrikclass Verwendung wie tf.RaggedTensor.from_value_rowids , tf.RaggedTensor.from_row_lengths und tf.RaggedTensor.from_row_splits .

tf.RaggedTensor.from_value_rowids

Wenn Sie wissen , welche Zeile jeder Wert gehört, dann können Sie einen bauen RaggedTensor ein mit value_rowids Reihe Partitionierungs Tensor:

value_rowids Zeilenpartitionierungs-Tensor

print(tf.RaggedTensor.from_value_rowids(
    values=[3, 1, 4, 1, 5, 9, 2],
    value_rowids=[0, 0, 0, 0, 2, 2, 3]))
<tf.RaggedTensor [[3, 1, 4, 1], [], [5, 9], [2]]>

tf.RaggedTensor.from_row_lengths

Wenn Sie wissen , wie lange jede Zeile ist, dann können Sie eine verwenden row_lengths Reihe Partitionierungs Tensor:

row_lengths Zeilenpartitionierungs-Tensor

print(tf.RaggedTensor.from_row_lengths(
    values=[3, 1, 4, 1, 5, 9, 2],
    row_lengths=[4, 0, 2, 1]))
<tf.RaggedTensor [[3, 1, 4, 1], [], [5, 9], [2]]>

tf.RaggedTensor.from_row_splits

Wenn Sie wissen , den Index in der jede Zeile beginnt und endet, dann können Sie eine verwenden row_splits Reihe Partitionierungs Tensor:

row_splits Zeilenpartitionierungs-Tensor

print(tf.RaggedTensor.from_row_splits(
    values=[3, 1, 4, 1, 5, 9, 2],
    row_splits=[0, 4, 4, 6, 7]))
<tf.RaggedTensor [[3, 1, 4, 1], [], [5, 9], [2]]>

Siehe die tf.RaggedTensor Klasse Dokumentation für eine vollständige Liste der Factory - Methoden.

Was Sie in einem zerlumpten Tensor speichern können

Wie bei normaler Tensor s, die Werte in einer RaggedTensor müssen alle die gleiche Art; und die Werte müssen alle auf dem gleichen Schachtelungstiefe (der Rang des Tensor) sein:

print(tf.ragged.constant([["Hi"], ["How", "are", "you"]]))  # ok: type=string, rank=2
<tf.RaggedTensor [[b'Hi'], [b'How', b'are', b'you']]>
print(tf.ragged.constant([[[1, 2], [3]], [[4, 5]]]))        # ok: type=int32, rank=3
<tf.RaggedTensor [[[1, 2], [3]], [[4, 5]]]>
try:
  tf.ragged.constant([["one", "two"], [3, 4]])              # bad: multiple types
except ValueError as exception:
  print(exception)
Can't convert Python sequence with mixed types to Tensor.
try:
  tf.ragged.constant(["A", ["B", "C"]])                     # bad: multiple nesting depths
except ValueError as exception:
  print(exception)
all scalar values must have the same nesting depth

Beispielanwendungsfall

Das folgende Beispiel zeigt , wie RaggedTensor s verwendet werden kann , konstruieren und Unigramm- und Bigramm Einbettungen für eine Charge von variabler Länge Abfragen, mit speziellen Markierungen für den Anfang und das Ende jeden Satz zu kombinieren. Weitere Einzelheiten zu den ops in diesem Beispiel verwendet wird , überprüfen Sie die tf.ragged Paketdokumentation.

queries = tf.ragged.constant([['Who', 'is', 'Dan', 'Smith'],
                              ['Pause'],
                              ['Will', 'it', 'rain', 'later', 'today']])

# Create an embedding table.
num_buckets = 1024
embedding_size = 4
embedding_table = tf.Variable(
    tf.random.truncated_normal([num_buckets, embedding_size],
                       stddev=1.0 / math.sqrt(embedding_size)))

# Look up the embedding for each word.
word_buckets = tf.strings.to_hash_bucket_fast(queries, num_buckets)
word_embeddings = tf.nn.embedding_lookup(embedding_table, word_buckets)     # ①

# Add markers to the beginning and end of each sentence.
marker = tf.fill([queries.nrows(), 1], '#')
padded = tf.concat([marker, queries, marker], axis=1)                       # ②

# Build word bigrams and look up embeddings.
bigrams = tf.strings.join([padded[:, :-1], padded[:, 1:]], separator='+')   # ③

bigram_buckets = tf.strings.to_hash_bucket_fast(bigrams, num_buckets)
bigram_embeddings = tf.nn.embedding_lookup(embedding_table, bigram_buckets) # ④

# Find the average embedding for each sentence
all_embeddings = tf.concat([word_embeddings, bigram_embeddings], axis=1)    # ⑤
avg_embedding = tf.reduce_mean(all_embeddings, axis=1)                      # ⑥
print(avg_embedding)
tf.Tensor(
[[-0.17446461  0.36370078 -0.27106178 -0.09025236]
 [-0.06600004 -0.23843841  0.09931535  0.32779136]
 [-0.00205609  0.10940682  0.05420941 -0.10945862]], shape=(3, 4), dtype=float32)

Beispiel für einen zackigen Tensor

Ausgefranste und einheitliche Abmessungen

Eine ragged Dimension eine Dimension , deren Scheiben können unterschiedliche Längen aufweisen. Zum Beispiel kann die innere (Spalte) Dimension rt=[[3, 1, 4, 1], [], [5, 9, 2], [6], []] ist zackig, da die Spaltenscheiben ( rt[0, :] , ..., rt[4, :] ) unterschiedliche Längen haben. Abmessungen , deren Scheiben haben alle die gleiche Länge sind einheitliche Abmessungen genannt.

Die äußerste Dimension eines zerlumpten Tensors ist immer einheitlich, da er aus einer einzigen Schicht besteht (und daher keine Möglichkeit für unterschiedliche Schichtlängen besteht). Die verbleibenden Abmessungen können entweder unregelmäßig oder einheitlich sein. Zum Beispiel können Sie das Wort Einbettungen für jedes Wort gespeichert werden in einer Charge von Sätzen einen zerlumpten Tensor mit Form unter Verwendung von [num_sentences, (num_words), embedding_size] , wo die Klammern (num_words) zeigen , dass die Dimension zackig ist.

Worteinbettungen mit einem zerlumpten Tensor

Zackige Tensoren können mehrere zackige Dimensionen haben. Zum Beispiel könnten Sie einen Stapel von strukturierten Textdokumenten speichern einen Tensor mit Form unter Verwendung von [num_documents, (num_paragraphs), (num_sentences), (num_words)] (wo wieder Klammern zerlumpte Dimensionen , um anzuzeigen , verwendet werden).

Wie bei tf.Tensor , ist der Rang eines ragged tensor seine Gesamtzahl der Dimensionen (einschließlich sowohl ausgefranste und einheitliche Abmessungen). Eine möglicherweise zackig Tensor ist ein Wert, der entweder eine sein könnte tf.Tensor oder ein tf.RaggedTensor .

Bei der Beschreibung der Form eines RaggedTensors werden unregelmäßige Dimensionen üblicherweise durch Einschließen in Klammern angegeben. Zum Beispiel, wie man oben gesehen, die Form eines 3D - RaggedTensor , dass Geschäfte Wort Einbettungen für jedes Wort in einer Charge von Sätzen können geschrieben werden als [num_sentences, (num_words), embedding_size] .

Das RaggedTensor.shape Attribut gibt einen tf.TensorShape für einen zerlumpten Tensor wo zerlumpte Dimensionen Größe haben None :

tf.ragged.constant([["Hi"], ["How", "are", "you"]]).shape
TensorShape([2, None])

Das Verfahren tf.RaggedTensor.bounding_shape kann verwendet werden , um eine enge Begrenzungsform für eine gegebene zu finden RaggedTensor :

print(tf.ragged.constant([["Hi"], ["How", "are", "you"]]).bounding_shape())
tf.Tensor([2 3], shape=(2,), dtype=int64)

Ragged vs spärlich

Ein zerlumpter Tensor soll nicht als eine Art spärlicher Tensor gedacht werden. Insbesondere spärlich Tensoren sind effiziente Codierungen für tf.Tensor , das Modell der gleichen Daten in einem kompakten Format; aber zackig Tensor ist eine Erweiterung tf.Tensor dass Modelle eine erweiterte Klasse von Daten. Dieser Unterschied ist entscheidend bei der Definition von Operationen:

  • Das Anwenden eines Ops auf einen dünn besetzten oder dichten Tensor sollte immer das gleiche Ergebnis liefern.
  • Das Anwenden einer Op auf einen ausgefransten oder spärlichen Tensor kann zu anderen Ergebnissen führen.

Als illustratives Beispiel betrachten , wie Array - Operationen wie concat , stack und tile definiert sind für ragged vs. sparse Tensoren. Das Verketten von zackigen Tensoren verbindet jede Reihe zu einer einzigen Reihe mit der kombinierten Länge:

Verkettung zerlumpter Tensoren

ragged_x = tf.ragged.constant([["John"], ["a", "big", "dog"], ["my", "cat"]])
ragged_y = tf.ragged.constant([["fell", "asleep"], ["barked"], ["is", "fuzzy"]])
print(tf.concat([ragged_x, ragged_y], axis=1))
<tf.RaggedTensor [[b'John', b'fell', b'asleep'], [b'a', b'big', b'dog', b'barked'], [b'my', b'cat', b'is', b'fuzzy']]>

Das Verketten von dünn besetzten Tensoren entspricht jedoch dem Verketten der entsprechenden dichten Tensoren, wie im folgenden Beispiel veranschaulicht (wobei Ø fehlende Werte angibt):

Verkettung von spärlichen Tensoren

sparse_x = ragged_x.to_sparse()
sparse_y = ragged_y.to_sparse()
sparse_result = tf.sparse.concat(sp_inputs=[sparse_x, sparse_y], axis=1)
print(tf.sparse.to_dense(sparse_result, ''))
tf.Tensor(
[[b'John' b'' b'' b'fell' b'asleep']
 [b'a' b'big' b'dog' b'barked' b'']
 [b'my' b'cat' b'' b'is' b'fuzzy']], shape=(3, 5), dtype=string)

Für ein weiteres Beispiel dafür , warum diese Unterscheidung ist wichtig, betrachten die Definition von „dem Mittelwert jeder Zeile“ für eine op wie tf.reduce_mean . Bei einem unregelmäßigen Tensor ist der Mittelwert für eine Zeile die Summe der Zeilenwerte geteilt durch die Zeilenbreite. Bei einem dünn besetzten Tensor ist der Mittelwert für eine Zeile jedoch die Summe der Zeilenwerte geteilt durch die Gesamtbreite des dünn besetzten Tensors (die größer oder gleich der Breite der längsten Zeile ist).

TensorFlow-APIs

Keras

tf.keras ist TensorFlow High-Level - API für den Aufbau und die Ausbildung tief Lernmodelle. Ragged Tensoren kann als Eingänge zu einem Keras Modell durch Setzen geben wird ragged=True auf tf.keras.Input oder tf.keras.layers.InputLayer . Ausgefranste Tensoren können auch zwischen Keras-Ebenen übergeben und von Keras-Modellen zurückgegeben werden. Das folgende Beispiel zeigt ein Spielzeug-LSTM-Modell, das mit Ragged Tensoren trainiert wird.

# Task: predict whether each sentence is a question or not.
sentences = tf.constant(
    ['What makes you think she is a witch?',
     'She turned me into a newt.',
     'A newt?',
     'Well, I got better.'])
is_question = tf.constant([True, False, True, False])

# Preprocess the input strings.
hash_buckets = 1000
words = tf.strings.split(sentences, ' ')
hashed_words = tf.strings.to_hash_bucket_fast(words, hash_buckets)

# Build the Keras model.
keras_model = tf.keras.Sequential([
    tf.keras.layers.Input(shape=[None], dtype=tf.int64, ragged=True),
    tf.keras.layers.Embedding(hash_buckets, 16),
    tf.keras.layers.LSTM(32, use_bias=False),
    tf.keras.layers.Dense(32),
    tf.keras.layers.Activation(tf.nn.relu),
    tf.keras.layers.Dense(1)
])

keras_model.compile(loss='binary_crossentropy', optimizer='rmsprop')
keras_model.fit(hashed_words, is_question, epochs=5)
print(keras_model.predict(hashed_words))
WARNING:tensorflow:Layer lstm will not use cuDNN kernels since it doesn't meet the criteria. It will use a generic GPU kernel as fallback when running on GPU.
Epoch 1/5
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/framework/indexed_slices.py:449: UserWarning: Converting sparse IndexedSlices(IndexedSlices(indices=Tensor("gradient_tape/sequential/lstm/RaggedToTensor/boolean_mask_1/GatherV2:0", shape=(None,), dtype=int32), values=Tensor("gradient_tape/sequential/lstm/RaggedToTensor/boolean_mask/GatherV2:0", shape=(None, 16), dtype=float32), dense_shape=Tensor("gradient_tape/sequential/lstm/RaggedToTensor/Shape:0", shape=(2,), dtype=int32))) to a dense Tensor of unknown shape. This may consume a large amount of memory.
  "shape. This may consume a large amount of memory." % value)
1/1 [==============================] - 2s 2s/step - loss: 7.7126
Epoch 2/5
1/1 [==============================] - 0s 18ms/step - loss: 7.7125
Epoch 3/5
1/1 [==============================] - 0s 16ms/step - loss: 7.7125
Epoch 4/5
1/1 [==============================] - 0s 16ms/step - loss: 7.7125
Epoch 5/5
1/1 [==============================] - 0s 18ms/step - loss: 7.7125
[[-0.01360238]
 [-0.01350192]
 [-0.01373475]
 [-0.01051904]]

tf.Beispiel

tf.Example ist ein Standard protobuf Codierung für TensorFlow Daten. Daten verschlüsselt mit tf.Example s oft auch mit variabler Länge Funktionen. Zum Beispiel definiert der folgende Code eine Charge von vier tf.Example Nachrichten mit unterschiedlichen Feature Längen:

import google.protobuf.text_format as pbtext

def build_tf_example(s):
  return pbtext.Merge(s, tf.train.Example()).SerializeToString()

example_batch = [
  build_tf_example(r'''
    features {
      feature {key: "colors" value {bytes_list {value: ["red", "blue"]} } }
      feature {key: "lengths" value {int64_list {value: [7]} } } }'''),
  build_tf_example(r'''
    features {
      feature {key: "colors" value {bytes_list {value: ["orange"]} } }
      feature {key: "lengths" value {int64_list {value: []} } } }'''),
  build_tf_example(r'''
    features {
      feature {key: "colors" value {bytes_list {value: ["black", "yellow"]} } }
      feature {key: "lengths" value {int64_list {value: [1, 3]} } } }'''),
  build_tf_example(r'''
    features {
      feature {key: "colors" value {bytes_list {value: ["green"]} } }
      feature {key: "lengths" value {int64_list {value: [3, 5, 2]} } } }''')]

Sie können diese codierten Daten unter Verwendung analysieren tf.io.parse_example , die einen Tensor serialisiert Strings und ein Feature - Spezifikation Wörterbuch und gibt eine Wörterbuch - Mapping - Funktion Namen zu Tensoren nimmt. Um die mit variabler Länge Funktionen in zerlumpte Tensoren zu lesen, verwenden Sie einfach tf.io.RaggedFeature in der Feature - Spezifikation Wörterbuch:

feature_specification = {
    'colors': tf.io.RaggedFeature(tf.string),
    'lengths': tf.io.RaggedFeature(tf.int64),
}
feature_tensors = tf.io.parse_example(example_batch, feature_specification)
for name, value in feature_tensors.items():
  print("{}={}".format(name, value))
colors=<tf.RaggedTensor [[b'red', b'blue'], [b'orange'], [b'black', b'yellow'], [b'green']]>
lengths=<tf.RaggedTensor [[7], [], [1, 3], [3, 5, 2]]>

tf.io.RaggedFeature kann auch Funktionen mit mehreren zerlumpten Dimensionen verwendet werden , um zu lesen. Weitere Einzelheiten finden Sie in der API - Dokumentation .

Datensätze

tf.data ist eine API , die Sie komplexe Eingangsleitungen von einfachen, wiederverwendbare Teile bauen ermöglicht. Sein Kerndatenstruktur ist tf.data.Dataset , die eine Folge von Elementen darstellt, wobei jedes Element aus einer oder mehreren Komponenten besteht.

# Helper function used to print datasets in the examples below.
def print_dictionary_dataset(dataset):
  for i, element in enumerate(dataset):
    print("Element {}:".format(i))
    for (feature_name, feature_value) in element.items():
      print('{:>14} = {}'.format(feature_name, feature_value))

Erstellen von Datensätzen mit unregelmäßigen Tensoren

Datensätze können aus ragged Tensoren gebaut werden mit den gleichen Methoden , die sie verwenden , bauen aus tf.Tensor s oder NumPy array s, wie Dataset.from_tensor_slices :

dataset = tf.data.Dataset.from_tensor_slices(feature_tensors)
print_dictionary_dataset(dataset)
Element 0:
        colors = [b'red' b'blue']
       lengths = [7]
Element 1:
        colors = [b'orange']
       lengths = []
Element 2:
        colors = [b'black' b'yellow']
       lengths = [1 3]
Element 3:
        colors = [b'green']
       lengths = [3 5 2]

Batching und Unbatching von Datensätzen mit unregelmäßigen Tensoren

Datensätze mit ragged Tensoren können (welche Mähdreschern n aufeinanderfolgenden Elemente in eine Einzelelemente) chargiert werden , um die Verwendung von Dataset.batch Methode.

batched_dataset = dataset.batch(2)
print_dictionary_dataset(batched_dataset)
Element 0:
        colors = <tf.RaggedTensor [[b'red', b'blue'], [b'orange']]>
       lengths = <tf.RaggedTensor [[7], []]>
Element 1:
        colors = <tf.RaggedTensor [[b'black', b'yellow'], [b'green']]>
       lengths = <tf.RaggedTensor [[1, 3], [3, 5, 2]]>

Umgekehrt kann ein batched Datensatz in einen flachen Datensatz umgewandelt wird unter Verwendung von Dataset.unbatch .

unbatched_dataset = batched_dataset.unbatch()
print_dictionary_dataset(unbatched_dataset)
Element 0:
        colors = [b'red' b'blue']
       lengths = [7]
Element 1:
        colors = [b'orange']
       lengths = []
Element 2:
        colors = [b'black' b'yellow']
       lengths = [1 3]
Element 3:
        colors = [b'green']
       lengths = [3 5 2]

Batchverarbeitung von Datensätzen mit nicht-ragged Tensoren variabler Länge

Wenn Sie einen Datensatz, die nicht-zackigen Tensoren enthält, und Tensor Längen variieren über Elemente, dann können Sie Batch jene nicht zerlumpt Tensoren in zerlumpten Tensoren durch die Anwendung dense_to_ragged_batch Transformation:

non_ragged_dataset = tf.data.Dataset.from_tensor_slices([1, 5, 3, 2, 8])
non_ragged_dataset = non_ragged_dataset.map(tf.range)
batched_non_ragged_dataset = non_ragged_dataset.apply(
    tf.data.experimental.dense_to_ragged_batch(2))
for element in batched_non_ragged_dataset:
  print(element)
<tf.RaggedTensor [[0], [0, 1, 2, 3, 4]]>
<tf.RaggedTensor [[0, 1, 2], [0, 1]]>
<tf.RaggedTensor [[0, 1, 2, 3, 4, 5, 6, 7]]>

Transformieren von Datensätzen mit unregelmäßigen Tensoren

Sie können auch zackig Tensoren in Daten - Sets erstellen oder zu transformieren Dataset.map :

def transform_lengths(features):
  return {
      'mean_length': tf.math.reduce_mean(features['lengths']),
      'length_ranges': tf.ragged.range(features['lengths'])}
transformed_dataset = dataset.map(transform_lengths)
print_dictionary_dataset(transformed_dataset)
Element 0:
   mean_length = 7
 length_ranges = <tf.RaggedTensor [[0, 1, 2, 3, 4, 5, 6]]>
Element 1:
   mean_length = 0
 length_ranges = <tf.RaggedTensor []>
Element 2:
   mean_length = 2
 length_ranges = <tf.RaggedTensor [[0], [0, 1, 2]]>
Element 3:
   mean_length = 3
 length_ranges = <tf.RaggedTensor [[0, 1, 2], [0, 1, 2, 3, 4], [0, 1]]>

tf.Funktion

tf.function ist ein Dekorateur , dass vorberechnet TensorFlow Graphen für Python - Funktionen, die im wesentlichen die Leistung Ihres TensorFlow Code verbessern können. Ragged Tensoren können transparent werden mit verwendet @tf.function -Dekoriert Funktionen. Die folgende Funktion funktioniert beispielsweise sowohl mit unregelmäßigen als auch mit nicht unregelmäßigen Tensoren:

@tf.function
def make_palindrome(x, axis):
  return tf.concat([x, tf.reverse(x, [axis])], axis)
make_palindrome(tf.constant([[1, 2], [3, 4], [5, 6]]), axis=1)
<tf.Tensor: shape=(3, 4), dtype=int32, numpy=
array([[1, 2, 2, 1],
       [3, 4, 4, 3],
       [5, 6, 6, 5]], dtype=int32)>
make_palindrome(tf.ragged.constant([[1, 2], [3], [4, 5, 6]]), axis=1)
2021-08-28 01:30:33.594827: W tensorflow/core/grappler/optimizers/loop_optimizer.cc:907] Skipping loop optimization for Merge node with control input: RaggedConcat/assert_equal_1/Assert/AssertGuard/branch_executed/_9
<tf.RaggedTensor [[1, 2, 2, 1], [3, 3], [4, 5, 6, 6, 5, 4]]>

Wenn Sie ausdrücklich wünschen , um die angeben input_signature für die tf.function , dann können Sie dies mit tf.RaggedTensorSpec .

@tf.function(
    input_signature=[tf.RaggedTensorSpec(shape=[None, None], dtype=tf.int32)])
def max_and_min(rt):
  return (tf.math.reduce_max(rt, axis=-1), tf.math.reduce_min(rt, axis=-1))

max_and_min(tf.ragged.constant([[1, 2], [3], [4, 5, 6]]))
(<tf.Tensor: shape=(3,), dtype=int32, numpy=array([2, 3, 6], dtype=int32)>,
 <tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 3, 4], dtype=int32)>)

Konkrete Funktionen

Konkrete Funktionen kapseln einzelne verfolgt Graphen , die durch gebaut werden tf.function . Ragged Tensoren können transparent mit konkreten Funktionen verwendet werden.

@tf.function
def increment(x):
  return x + 1

rt = tf.ragged.constant([[1, 2], [3], [4, 5, 6]])
cf = increment.get_concrete_function(rt)
print(cf(rt))
<tf.RaggedTensor [[2, 3], [4], [5, 6, 7]]>

Gespeicherte Modelle

A SavedModel ist eine serialisierte TensorFlow Programm, beide Gewichte und Berechnung einschließlich. Es kann aus einem Keras-Modell oder aus einem benutzerdefinierten Modell erstellt werden. In beiden Fällen können unregelmäßige Tensoren transparent mit den von einem SavedModel definierten Funktionen und Methoden verwendet werden.

Beispiel: Speichern eines Keras-Modells

import tempfile

keras_module_path = tempfile.mkdtemp()
tf.saved_model.save(keras_model, keras_module_path)
imported_model = tf.saved_model.load(keras_module_path)
imported_model(hashed_words)
WARNING:absl:Function `_wrapped_model` contains input name(s) args_0 with unsupported characters which will be renamed to args_0_1 in the SavedModel.
2021-08-28 01:30:34.510653: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
INFO:tensorflow:Assets written to: /tmp/tmp8uiis25m/assets
INFO:tensorflow:Assets written to: /tmp/tmp8uiis25m/assets
<tf.Tensor: shape=(4, 1), dtype=float32, numpy=
array([[-0.01360238],
       [-0.01350192],
       [-0.01373475],
       [-0.01051904]], dtype=float32)>

Beispiel: Speichern eines benutzerdefinierten Modells

class CustomModule(tf.Module):
  def __init__(self, variable_value):
    super(CustomModule, self).__init__()
    self.v = tf.Variable(variable_value)

  @tf.function
  def grow(self, x):
    return x * self.v

module = CustomModule(100.0)

# Before saving a custom model, you must ensure that concrete functions are
# built for each input signature that you will need.
module.grow.get_concrete_function(tf.RaggedTensorSpec(shape=[None, None],
                                                      dtype=tf.float32))

custom_module_path = tempfile.mkdtemp()
tf.saved_model.save(module, custom_module_path)
imported_model = tf.saved_model.load(custom_module_path)
imported_model.grow(tf.ragged.constant([[1.0, 4.0, 3.0], [2.0]]))
INFO:tensorflow:Assets written to: /tmp/tmp3ad14pef/assets
INFO:tensorflow:Assets written to: /tmp/tmp3ad14pef/assets
<tf.RaggedTensor [[100.0, 400.0, 300.0], [200.0]]>

Überlastete Operatoren

Die RaggedTensor Klasse Überlastungen die Standard - Python - Arithmetik und Vergleichsoperatoren, so dass es einfach grundlegende mathematische element auszuführen:

x = tf.ragged.constant([[1, 2], [3], [4, 5, 6]])
y = tf.ragged.constant([[1, 1], [2], [3, 3, 3]])
print(x + y)
<tf.RaggedTensor [[2, 3], [5], [7, 8, 9]]>

Da die überladenen Operatoren elementweise Berechnungen durchführen, müssen die Eingaben für alle binären Operationen dieselbe Form haben oder an dieselbe Form übertragen werden können. Im einfachsten Broadcasting-Fall wird ein einzelner Skalar elementweise mit jedem Wert in einem zackigen Tensor kombiniert:

x = tf.ragged.constant([[1, 2], [3], [4, 5, 6]])
print(x + 3)
<tf.RaggedTensor [[4, 5], [6], [7, 8, 9]]>

Für eine Diskussion von fortgeschrittenen Fällen, überprüfen Sie den Abschnitt über den Rundfunk.

Ragged Tensoren überlasten den gleichen Satz von Operatoren wie normale Tensor s: die unäre Operatoren - , ~ , und abs() ; und die binären Operatoren + , - , * , / , // , % , ** , & , | , ^ , == , < , <= , > und >= .

Indizierung

Ragged Tensoren unterstützen Indizierung im Python-Stil, einschließlich mehrdimensionaler Indizierung und Slicing. Die folgenden Beispiele veranschaulichen die Indexierung von Ragged-Tensoren mit einem 2D- und einem 3D-Ragged-Tensor.

Indizierungsbeispiele: 2D-Zackentensor

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']]>
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']]>

Indizierungsbeispiele: 3D-Zacken-Tensor

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]]]>

RaggedTensor Unterstützung mehrdimensionale Indizierung und Aufschneiden mit einer Einschränkung: Indizieren in eine zackige Dimension ist nicht erlaubt. Dieser Fall ist problematisch, da der angezeigte Wert in einigen Zeilen vorhanden sein kann, in anderen jedoch nicht. In solchen Fällen ist es nicht klar , ob Sie sollten (1) eine erhöhen IndexError ; (2) einen Standardwert verwenden; oder (3) diesen Wert überspringen und einen Tensor mit weniger Zeilen zurückgeben, als Sie mit begonnen haben. Nach den Leitsätzen von Python ( „Im Angesicht der Mehrdeutigkeit, sie weigern , die Versuchung zu guess“), wird dieser Vorgang zur Zeit nicht erlaubt.

Konvertierung des Tensortyps

Die RaggedTensor Klasse definiert Methoden , die verwendet werden können , zwischen konvertieren RaggedTensor s und tf.Tensor s oder 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']]>

Auswerten von zerlumpten Tensoren

Um auf die Werte in einem unregelmäßigen Tensor zuzugreifen, können Sie:

  1. Verwenden tf.RaggedTensor.to_list den zackigen Tensor auf eine verschachtelte Python - Liste zu konvertieren.
  2. Verwendung tf.RaggedTensor.numpy den zackigen Tensor einer NumPy Array deren Werte verschachtelt NumPy Arrays zu konvertieren.
  3. Zersetzen sich die ragged Tensor in seine Komponenten, die unter Verwendung von tf.RaggedTensor.values und tf.RaggedTensor.row_splits Eigenschaften oder Zeilen partitionieren Methoden wie tf.RaggedTensor.row_lengths und tf.RaggedTensor.value_rowids .
  4. Verwenden Sie die Python-Indizierung, um Werte aus dem unregelmäßigen Tensor auszuwählen.
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]
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/ragged/ragged_tensor.py:2063: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
  return np.array(rows)

Rundfunk

Broadcasting ist der Prozess, bei dem Tensoren mit unterschiedlichen Formen kompatible Formen für elementweise Operationen haben. Weitere Hintergrundinformationen zum Rundfunk finden Sie unter:

Die grundlegenden Schritte für die Übertragung zwei Eingänge x und y kompatible Formen aufweisen , sind:

  1. Wenn x und y nicht die gleiche Anzahl von Dimensionen haben, dann Außenabmessungen addieren (mit einer Größe von 1) , bis sie es tun.

  2. Für jede Dimension , in der x und y haben unterschiedliche Größen:

  • Wenn x oder y Größe haben 1 in Dimension d , dann wiederholen ihre Werte über Dimension d der anderen Eingangsgröße anzupassen.
  • Andernfalls erhöhen , eine Ausnahme ( x und y sind nicht kompatibel ausgestrahlt).

Wobei die Größe eines Tensors in einer einheitlichen Dimension eine einzelne Zahl ist (die Größe der Slices über diese Dimension); und die Größe eines Tensors in einer unregelmäßigen Dimension ist eine Liste von Slice-Längen (für alle Slices in dieser Dimension).

Sendebeispiele

# 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]]]]>

Hier sind einige Beispiele für Formen, die nicht übertragen werden:

# 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)
Expected 'tf.Tensor(False, shape=(), dtype=bool)' to be true. Summarized data: b'Unable to broadcast: dimension size mismatch in dimension'
1
b'lengths='
4
b'dim_size='
2, 4, 1
# 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)
Expected 'tf.Tensor(False, shape=(), dtype=bool)' to be true. Summarized data: b'Unable to broadcast: dimension size mismatch in dimension'
1
b'lengths='
2, 2, 1
b'dim_size='
3, 1, 2
# 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)
Expected 'tf.Tensor(False, shape=(), dtype=bool)' to be true. Summarized data: b'Unable to broadcast: dimension size mismatch in dimension'
2
b'lengths='
3, 3, 3, 3, 3
b'dim_size='
2, 2, 2, 2, 2

RaggedTensor-Kodierung

Ragged Tensoren sind codiert , um die Verwendung von RaggedTensor Klasse. Intern jedes RaggedTensor besteht aus:

  • A values Tensor, der die Zeilen variabler Länge in eine abgeflachte Liste verkettet.
  • A row_partition , das angibt , wie diese abgeflachte Werte werden in Zeilen unterteilt.

RaggedTensor-Kodierung

Die row_partition kann mit vier verschiedenen Kodierungen gespeichert werden:

  • row_splits eine ganze Zahl Vektor die Teilungspunkte zwischen Zeilen angibt.
  • value_rowids eine ganze Zahl Vektor den Zeilenindex für jeden Wert angeben.
  • row_lengths eine ganze Zahl Vektor , der die Länge jeder Zeile angibt.
  • uniform_row_length eine ganze Zahl skalaren eine einzige Länge für alle Zeilen angibt.

row_partition-Kodierungen

Eine ganze Zahl skalaren nrows kann auch in der enthalten sein row_partition Codierung Konto für leere Zeilen mit nachlauf value_rowids oder leeren Zeilen mit 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]]>

Die Wahl der für Zeilenpartitionen zu verwendenden Codierung wird intern von unregelmäßigen Tensoren verwaltet, um die Effizienz in einigen Kontexten zu verbessern. Einige der Vor- und Nachteile der verschiedenen Zeilenpartitionierungsschemata sind insbesondere:

  • Effiziente Indizierung: Die row_splits Codierung ermöglicht konstante Zeitindizierung und Schneiden in zerlumpten Tensoren.
  • Effiziente Verkettung: Die row_lengths kodierend ist effizienter , wenn ragged Tensoren verketten, da Zeilenlängen ändern sich nicht , wenn zwei Tensoren miteinander verkettet sind.
  • Kleine Codierung Größe: Die value_rowids kodiert , ist effizienter , wenn zerlumpte Tensoren zu speichern , die eine große Anzahl von leeren Zeilen haben, da die Größe des Tensor nur auf der Gesamtzahl der Werte abhängen. Auf der anderen Seite sind die row_splits und row_lengths sind Codierungen effizienter , wenn zerlumpten Tensoren mit längeren Reihen speichern, da sie für jede Zeile nur einen skalaren Wert erfordern.
  • Kompatibilität: Das value_rowids Schema entspricht das Segmentierungsformat , das von Operationen, wie verwendet tf.segment_sum . Das row_limits Schema entspricht das Format von ops wie verwendet tf.sequence_mask .
  • Einheitliche Abmessungen: wie unten diskutiert, die uniform_row_length Kodierung zu kodieren , verwendet wird zackig Tensoren mit einheitlichen Abmessungen.

Mehrere unregelmäßige Dimensionen

Ein ragged Tensor mit mehreren ragged Dimensionen unter Verwendung eines verschachtelten codierten RaggedTensor für die values Tensors. Jede verschachtelte RaggedTensor fügt eine einzelne zerlumpte Dimension.

Kodierung eines Ragged-Tensors mit mehreren Ragged-Dimensionen (Rang 2)

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

Die Werksfunktion tf.RaggedTensor.from_nested_row_splits kann durch die Bereitstellung einer Liste einer RaggedTensor mit mehreren Dimensionen ragged direkt zu konstruieren , verwendet werden row_splits Tensoren:

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]]]>

Ragged Rang und flache Werte

Ein zerlumpter Rang des zackigen Tensor ist die Anzahl der Male , dass die zugrunde liegenden values Tensor aufgeteilt wurde (dh die Schachtelungstiefe RaggedTensor Objekte). Die innersten values Tensor als flat_values bekannt ist. Im folgenden Beispiel conversations hat ragged_rank = 3, und seine flat_values ist ein 1D - Tensor mit 24 Saiten:

# 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)

Einheitliche Innenmaße

Ragged Tensoren mit einheitlicher Innenabmessung wird unter Verwendung eines mehrdimensionalen codierten tf.Tensor für die flat_values (dh die innersten values ).

Codierung von Ragged Tensoren mit einheitlichen Innenabmessungen

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]]

Einheitliche Nicht-Innenmaße

Ragged Tensoren mit nicht-gleichförmigen inneren Abmessungen werden durch Partitionieren Reihen mit codierten uniform_row_length .

Codierung von unregelmäßigen Tensoren mit einheitlichen nicht-inneren Abmessungen

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