[PYTHON] [TensorFlow] Ich möchte die Indizierung für Ragged Tensor beherrschen

Einführung

Ragged Tensor, der Daten variabler Länge darstellt, die in TensorFlow 2.1 oder höher eingeführt wurden, aber beim Versuch, mit gewöhnlichem Tensor-Kleber zu schreiben, verschiedene Ich bin süchtig danach. Diesmal ist Indizierung. Versuchen Sie, den Wert von RaggedTensor abzurufen, indem Sie einen bestimmten Index angeben. Wenn Sie sich daran gewöhnt haben, können Sie komplizierte Operationen ausführen ...

Überprüfungsumgebung

Indizierungsbeispiel

Angenommen, x wird als RaggedTensor erstellt, der wie folgt indiziert werden soll.

x = tf.RaggedTensor.from_row_lengths(tf.range(15), tf.range(1, 6))
print(x)
# <tf.RaggedTensor [[0], [1, 2], [3, 4, 5], [6, 7, 8, 9], [10, 11, 12, 13, 14]]>
Spaltenindex 0 1 2 3 4
Zeile 0 0
Die erste Zeile 1 2
2. Zeile 3 4 5
3. Zeile 6 7 8 9
4. Zeile 10 11 12 13 14

Schneiden auf einer bestimmten Linie

Die erste Operation besteht darin, eine Zeile abzurufen, die der eines normalen "Tensors" entspricht. Sie können es sich als "numpy.ndarray" vorstellen. Wenn Sie einen Bereich angeben, enthält ** den ersten Index und nicht den letzten Index. ** Wenn Sie ein Python-Benutzer sind, gibt es meines Erachtens kein Problem.

print(x[2])
# tf.Tensor([3 4 5], shape=(3,), dtype=int32)
print(x[1:4])
# <tf.RaggedTensor [[1, 2], [3, 4, 5], [6, 7, 8, 9]]>

Im Gegensatz zu "numpy.ndarray" scheint es jedoch nicht möglich zu sein, Slicing zu verwenden, das diskrete Zeilen angibt.

#Dies kann für ndarray durchgeführt werden
print(x.numpy()[[1, 3]])                                                                                                                    
# [array([1, 2], dtype=int32) array([6, 7, 8, 9], dtype=int32)]

# Tensor/Nicht verfügbar für Ragged Tensor
print(x[[1, 3]])
# InvalidArgumentError: slice index 3 of dimension 0 out of bounds. [Op:StridedSlice] name: strided_slice/

Bitte gehen Sie stattdessen hierher.

# Tensor/Ausgefallene Indizierung mit Ragged Tensor
print(tf.gather(x, [1, 3], axis=0))
# <tf.RaggedTensor [[1, 2], [6, 7, 8, 9]]>

Schneiden mit festem Spaltenindex

Das Folgende ist ein Beispiel für das Schneiden mit einem festen Spaltenindex. Im Gegensatz zu gewöhnlichem Tensor hängt es von der Zeile ab, ob es ein Element des Index gibt oder nicht, also einfach

print(x[:, 2])
# ValueError: Cannot index into an inner ragged dimension.

Es ist nicht möglich, wie zu tun. Wenn Sie den Bereich angeben

print(x[:, 2:3])
# <tf.RaggedTensor [[], [], [5], [8], [12]]>

Es funktioniert wie. Es ist [] für die Zeile, in der der angegebene Index nicht existiert.

Spaltenindex 0 1 2 3 4
Zeile 0 0
Die erste Zeile 1 2
2. Zeile 3 4 5
3. Zeile 6 7 8 9
4. Zeile 10 11 12 13 14

Schneiden mit einem anderen Spaltenindex für jede Zeile

Wenn Sie einen Tensor haben, der die zweidimensionalen Indizes auflistet, die Sie sammeln möchten, können Sie tf.gather_nd () verwenden.

ind = tf.constant([[0, 0], [1, 1], [2, 0], [4, 3]])
#x(0, 0), (1, 1), (2, 0), (4, 3)Ich möchte Elemente sammeln
print(tf.gather_nd(x, ind))
# tf.Tensor([ 0  2  3 13], shape=(4,), dtype=int32)
Spaltenindex 0 1 2 3 4
Zeile 0 0
Die erste Zeile 1 2
2. Zeile 3 4 5
3. Zeile 6 7 8 9
4. Zeile 10 11 12 13 14

Andererseits rufe ich ein Element für jede Zeile ab, aber ich denke, es gibt Zeiten, in denen Sie aus verschiedenen Spalten abrufen möchten.

col = tf.constant([0, 0, 2, 1, 2])
#x(0, 0), (1, 0), (2, 2), (3, 1), (4, 2)Ich möchte Elemente sammeln
#Fügen Sie dem Index Zeilennummern hinzu und verwenden Sie dann dieselbe Methode wie zuvor
ind = tf.transpose(tf.stack([tf.range(tf.shape(col)[0]), col]))
print(tf.gather_nd(x, ind))
# tf.Tensor([ 0  1  5  7 12], shape=(5,), dtype=int32)
Spaltenindex 0 1 2 3 4
Zeile 0 0
Die erste Zeile 1 2
2. Zeile 3 4 5
3. Zeile 6 7 8 9
4. Zeile 10 11 12 13 14

Aber ich habe das Gefühl, dass es spät sein wird, also habe ich über einen intelligenteren Weg nachgedacht.

print(tf.gather(x.values, x.row_starts() + col))
# tf.Tensor([ 0  1  5  7 12], shape=(5,), dtype=int32)

Das ist in Ordnung. Der tatsächliche Wert von "x" ist in "Tensor" (nicht "RaggedTensor") enthalten, der jede Linie verbindet (eine Dimension weniger) und durch Zugriff auf "x.values" erhalten werden kann. Ich werde. Es enthält auch Informationen über den Startindex jeder Zeile (x.row_starts ()), um die Form von x darzustellen. Daher können Sie den angegebenen Offset zu diesem Index hinzufügen und gegen "x.values" schneiden.

%timeit tf.gather_nd(x, tf.transpose(tf.stack([tf.range(tf.shape(col)[0]), col])))
# 739 µs ± 75.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit tf.gather(x.values, x.row_starts() + col)                                                                                           
# 124 µs ± 6.47 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Dieser ist schneller (^_^)

Wenn Sie die Operation hier beherrschen möchten, ist es gut, das offizielle Dokument zu sehen.

Wenn sich der Spaltenindex in einem Ragged Tensor befindet

Wenden Sie das obige "die Substanz des Wertes ist in dem eindimensionalen" Tensor "" an.

col = tf.ragged.constant([[0], [], [0, 2], [1, 3], [2]])
#x(0, 0), (2, 0), (2, 2), (3, 1), (3, 3), (4, 2)Ich möchte Elemente sammeln

#Holen Sie sich den Startindex jeder Zeile von x
row_starts = tf.cast(x.row_starts(), "int32")
#Rufen Sie die Zeilennummer ab, zu der jede Komponente von col gehört, konvertieren Sie sie in den Startindex bei x und fügen Sie den Offset hinzu
ind_flat = tf.gather(row_starts, col.value_rowids()) + col.values
ret = tf.gather(x.values, ind_flat)
print(ret)
# tf.Tensor([ 0  3  5  7  9 12], shape=(6,), dtype=int32)
Spaltenindex 0 1 2 3 4
Zeile 0 0
Die erste Zeile 1 2
2. Zeile 3 4 5
3. Zeile 6 7 8 9
4. Zeile 10 11 12 13 14

Wenn Sie die Informationen der ursprünglichen Zeile speichern möchten

Das obige Ergebnis ist ein normaler "Tensor" mit den aufgelisteten Werten, und die Informationen in der ursprünglichen Zeile gehen verloren. Was ist jedoch, wenn Sie die Zeileninformationen speichern möchten? Sie können einen RaggedTensor erstellen, indem Sie dem Tensor Informationen über den Zeilenstartindex geben. Die Länge jeder Zeile sollte mit col übereinstimmen, damit Sie diesen Startindex von col.value_rowids () erhalten können.

print(tf.RaggedTensor.from_value_rowids(ret, col.value_rowids()))
# <tf.RaggedTensor [[0], [], [3, 5], [7, 9], [12]]>

Wenn der Ziel-Ragged-Tensor 3 Dimensionen oder mehr hat

Selbst wenn Daten mit 2 oder mehr Dimensionen in chronologischer Reihenfolge angeordnet sind (3 oder mehr Dimensionen für "RaggedTensor" einschließlich Chargenabmessungen), kann die vorhandene Methode unverändert verwendet werden.

x = tf.RaggedTensor.from_row_lengths(tf.reshape(tf.range(30), (15, 2)), tf.range(1, 6))
print(x)
# <tf.RaggedTensor [[[0, 1]], [[2, 3], [4, 5]], [[6, 7], [8, 9], [10, 11]], [[12, 13], [14, 15], [16, 17], [18, 19]], [[20, 21], [22, 23], [24, 25], [26, 27], [28, 29]]]>

Die Struktur dieses "x" kann wie folgt interpretiert werden.

Spaltenindex 0 1 2 3 4
Zeile 0 [0, 1]
Die erste Zeile [2, 3] [4, 5]
2. Zeile [6, 7] [8, 9] [10, 11]
3. Zeile [12, 13] [14, 15] [16, 17] [18, 19]
4. Zeile [20, 21] [22, 23] [24, 25] [26, 27] [28, 29]

Der Rest ist genau der gleiche wie zuvor. Bitte beachten Sie jedoch, dass der zurückgegebene "Tensor" zweidimensional ist.

ind = tf.constant([[0, 0], [1, 1], [2, 0], [4, 3]])
#x(0, 0), (1, 1), (2, 0), (4, 3)Ich möchte Elemente sammeln
print(tf.gather_nd(x, ind))
# tf.Tensor(
# [[ 0  1]
#  [ 4  5]
#  [ 6  7]
#  [26 27]], shape=(4, 2), dtype=int32)
col = tf.constant([0, 0, 2, 1, 2])
#x(0, 0), (1, 0), (2, 2), (3, 1), (4, 2)Ich möchte Elemente sammeln
print(tf.gather(x.values, x.row_starts() + col))
# tf.Tensor(
# [[ 0  1]
#  [ 2  3]
#  [10 11]
#  [14 15]
#  [24 25]], shape=(5, 2), dtype=int32)
col = tf.ragged.constant([[0], [], [0, 2], [1, 3], [2]])
#x(0, 0), (2, 0), (2, 2), (3, 1), (3, 3), (4, 2)Ich möchte Elemente sammeln

#Holen Sie sich den Startindex jeder Zeile von x
row_starts = tf.cast(x.row_starts(), "int32")
#Rufen Sie die Zeilennummer ab, zu der jede Komponente von col gehört, konvertieren Sie sie in den Startindex bei x und fügen Sie den Offset hinzu
ind_flat = tf.gather(row_starts, col.value_rowids()) + col.values
ret = tf.gather(x.values, ind_flat)
print(ret)
# tf.Tensor(
# [[ 0  1]
#  [ 6  7]
#  [10 11]
#  [14 15]
#  [18 19]
#  [24 25]], shape=(6, 2), dtype=int32)

#Wenn Sie die Informationen der ursprünglichen Zeile speichern möchten
print(tf.RaggedTensor.from_value_rowids(ret, col.value_rowids()))
# <tf.RaggedTensor [[[0, 1]], [], [[6, 7], [10, 11]], [[14, 15], [18, 19]], [[24, 25]]]>

Recommended Posts

[TensorFlow] Ich möchte die Indizierung für Ragged Tensor beherrschen
[TensorFlow] Ich möchte Fenster mit Ragged Tensor verarbeiten
Ich habe versucht, den für TensorFlow geschriebenen Code nach Theano zu portieren
Ich möchte vorerst Selen bewegen [für Mac]
Ich möchte vorerst eine Docker-Datei erstellen.
[Für diejenigen, die TPU verwenden möchten] Ich habe versucht, die Tensorflow Object Detection API 2 zu verwenden
Vorerst möchte ich jede Datei mit ffmpeg konvertieren !!
Ich möchte Spyder an die Taskleiste anheften
Ich möchte kühl auf die Konsole ausgeben
Ich habe zum ersten Mal Tensorflow ausprobiert
Ich möchte mit dem Reim Teil1 umgehen
Ich möchte mit dem Reim part3 umgehen
Ich möchte den Fortschrittsbalken anzeigen
Ich möchte mit dem Reim part2 umgehen
Ich möchte mit dem Reim part5 umgehen
Ich möchte mit dem Reim part4 umgehen
Der schnellste Weg für Anfänger, um Python zu beherrschen
Ich möchte mit dem Reim part7 (BOW) umgehen
[Ich möchte Bilder mit Tensorflow klassifizieren] (2) Lassen Sie uns Bilder klassifizieren
Ich möchte das Erscheinungsbild von zabbix anpassen
Ich möchte die Aktivierungsfunktion Mish verwenden
Ich möchte den Fortschritt in Python anzeigen!
Ich möchte dem Anfang einer WAV-Datei 1 Sekunde lang Stille hinzufügen
Ich möchte den Dateinamen von DataLoader sehen
Ich möchte mich mit Backpropagation (tf.custom_gradient) (Tensorflow) selbst verwenden.
Ich möchte das Ausführungsergebnis von strace erfassen
Ich möchte in der Django-Verschiebungstabelle scrollen, aber ...
Ich habe das MNIST-Tutorial von tensorflow für Anfänger ausprobiert.
Ich möchte mit Python-Datenklasse nach hinten erben
Ich möchte die Grundlagen von Bokeh vollständig verstehen
Ich möchte in Python schreiben! (3) Verwenden Sie Mock
Ich möchte mit dem Reim part6 umgehen (einmal organisieren)
Ich möchte ssh mit dem Befehl expected automatisieren!
Ich möchte das Produkt zu den niedrigsten Kosten veröffentlichen
Ich möchte R-Datensatz mit Python verwenden
Ich möchte mit dem Reim part8 umgehen (einmal fertig)
Ich möchte die Sicherheit der SSH-Verbindung erhöhen
Ich möchte nur das 95% -Konfidenzintervall des Unterschieds im Bevölkerungsverhältnis in Python ermitteln
Ich möchte zum ersten Mal eine Django-Studie zur Mittagsdatenbank [EP1] erstellen
Ich möchte zum ersten Mal eine Django-Studie zum Mittagessen [EP1-4] erstellen
Ich möchte das neueste gcc verwenden, auch wenn ich keine Sudo-Berechtigungen habe! !!
Ich möchte initialisieren, wenn der Wert leer ist (Python)
Ich möchte die von LINE an S3 gesendeten Fotos speichern
Ich möchte Geschenke auch für mich selbst austauschen! [Weihnachten Hackason]
Ich habe versucht, mit TensorFlow den Durchschnitt mehrerer Spalten zu ermitteln
Ich möchte ssh mit dem Befehl expected automatisieren! Teil 2
maya Python Ich möchte die gebackene Animation wieder reparieren.
Ich möchte etwas Schönes sehen, also habe ich versucht, die Funktion zu visualisieren, die zum Benchmarking der Optimierungsfunktion verwendet wird.
[NetworkX] Ich möchte nach Knoten mit bestimmten Attributen suchen
[Für Anfänger] Ich möchte die Anzahl der Lernerfahrungen leicht verständlich erklären.
Ich möchte nur die SudachiPy-Normalisierungsverarbeitung verwenden
Ich möchte Betriebsinformationen über die Yahoo-Route erhalten
Ich möchte mit Numpy die japanische Flagge in die Palau-Flagge ändern
Ich möchte SUDOKU lösen
Für diejenigen, die mit TensorFlow2 maschinelles Lernen beginnen möchten
Ich möchte die zulässige Ausfallzeit aus der Betriebsrate berechnen
[Python] Ich möchte die Option -h mit argparse verwenden
Ich möchte den Unterschied zwischen der for-Anweisung in der Python + numpy-Matrix und der Julia for-Anweisung auffangen
Ich möchte die Authentizität eines Elements eines numpy-Arrays bestimmen
Ich wusste nicht, wie ich die [Python] für die Anweisung verwenden sollte
Ich möchte vorerst die Desktop-Umgebung von Ubuntu auf Android verwenden (Termux-Version)