[PYTHON] Vorsichtsmaßnahmen bei der Verwendung von tf.keras.layers.TimeDistributed für die benutzerdefinierte Ebene von tf.keras

Zweck dieses Artikels

tf.tf für benutzerdefinierte Ebene in Keras definiert.keras.layers.Bei der Verwendung von TimeDistributed ist ein Fehler aufgetreten, daher werde ich den Inhalt und die Lösung freigeben.



 version
- Python: 3.6.9
- Tensorflow: 2.1.0

## Inhaltsverzeichnis
 --Was ist tf.keras.layers.TimeDistributed?
 --Was ist eine benutzerdefinierte Ebene?
 - Einführung von Fehlerinhalten, wenn tf.keras.layers.TimeDistributed auf eine benutzerdefinierte Ebene angewendet wird
 - Lösung oben

## Was ist tf.keras.layers.TimeDistributed?
 Es wird verwendet, wenn Sie möchten, dass eine Ebene wiederholt in Zeitrichtung wirkt. ([Referenz](https://www.tensorflow.org/api_docs/python/tf/keras/layers/TimeDistributed))

```python
from tensorflow.keras import Input, Model
from tensorflow.keras.layers import TimeDistributed, Dense

temporal_dim = 4
emb_dim = 16
inputs = Input((temporal_dim, 8))
outputs = TimeDistributed(Dense(emb_dim))(inputs)
model = Model(inputs, outputs)
model.summary()
"""
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 4, 8)]            0         
_________________________________________________________________
time_distributed (TimeDistri (None, 4, 16)             144       
=================================================================
Total params: 144
Trainable params: 144
Non-trainable params: 0
_________________________________________________________________
"""

Hinweis) Das obige Ergebnis ist unabhängig vom Vorhandensein oder Fehlen von `tf.keras.layers.TimeDistributed```, da` tf.keras.layers.Dense``` nur die letzte Dimension betrifft. Ich bin dankbar, wenn ich es für Ebenen mit begrenzter Eingabeform verwende, z. B. "tf.keras.layers.Embedding".

tf.keras.layers.Das Einbetten ist Batch_Es kann nur für 2D-Tensoren mit Größe verwendet werden. Wenn Sie also 3D-Tensoren einbetten möchten, tf.keras.layers.Sie müssen TimeDistributed verwenden, um die fehlende zusätzliche eindimensionale Richtung zu durchlaufen.(Wird im empfohlenen Modell verwendet)


## Was ist eine benutzerdefinierte Ebene?

#### **`tf.In Keras, tf.keras.layers.Sie können eine Ebene erben, um eine benutzerdefinierte Ebene zu definieren.`**

tf.In Keras sind viele nützliche Ebenen implementiert, die Sie zu tf kombinieren können..keras.Wir werden ein Modell erstellen. Eine große Anzahl von Modellen kann nur mit der Standardschicht implementiert werden.



 Wenn Sie eine flexiblere Verarbeitung wünschen, können Sie diese als benutzerdefinierte Ebene implementieren, ohne die Ähnlichkeit "tf.keras" zu verlieren. ([Referenz](https://www.tensorflow.org/tutorials/customization/custom_layers))

### Beispiel .1: Kombinieren Sie Standard `` `tf.keras.layers```
 Verwenden Sie in diesem Fall `` `.__ init__ ()` ``, um eine Instanz von` `tf.keras.layers``` zu generieren, und verwenden Sie` `` .call () `` `, um die eigentliche Ebene zu verarbeiten. Ist definiert.

 (Die folgenden Ebenen sind identisch mit `` `tf.keras.layers.Dense```)

```python
import tensorflow as tf
from tensorflow.keras.layers import Dense

class Linear(tf.keras.layers.Layer):
    def __init__(self, emb_dim, *args, **kwargs):
        super(Linear_error, self).__init__(*args, **kwargs)
        self.dense = Dense(emb_dim)

    def call(self, x):
        return self.dense(x)

Beispiel .2: Definieren Sie eine lernbare Variable

Um die untergeordnete API zu verwenden, können Sie Folgendes schreiben:

class Linear(tf.keras.layers.Layer):
    def __init__(self, emb_dim):
        super(Linear, self).__init__()
        self.emb_dim = emb_dim

    def build(self, input_shape):
        self.kernel = self.add_weight(
            "kernel", shape=[int(input_shape[-1]), self.emb_dim]
        )

    def call(self, x):
        return tf.matmul(x, self.kernel)

Fehler: tf.keras.layers.TimeDistributed für benutzerdefinierte Ebene funktioniert nicht

Verwenden Sie `` `tf.keras.layers.TimeDistributed``` für benutzerdefinierte Ebenen, wie unten gezeigt.

from tensorflow.keras import Input
from tensorflow.keras.layers import TimeDistributed

temporal_dim = 4
emb_dim = 16
inputs = Input((temporal_dim, 8))

outputs = TimeDistributed(Linear(emb_dim))(inputs)
assert outputs.shape.rank == 3
assert outputs.shape[1] == temporal_dim
assert outputs.shape[2] == emb_dim

Dann wird der folgende Fehler zurückgegeben. (Auszug)

/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/engine/base_layer.py:773: in __call__
    outputs = call_fn(cast_inputs, *args, **kwargs)
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/layers/wrappers.py:270: in call
    output_shape = self.compute_output_shape(input_shape).as_list()
/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/layers/wrappers.py:212: in compute_output_shape
    child_output_shape = self.layer.compute_output_shape(child_input_shape)

>     raise NotImplementedError
E     NotImplementedError

/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/keras/engine/base_layer.py:564: NotImplementedError

Dies ist eine Meldung, dass die benutzerdefinierte Ebene `.compute_output_shape ()` fehlt. Implementieren Sie sie daher bitte selbst.

In tf.keras.layers werden input_shape und output_shape erst bestimmt, wenn `.build ()` oder .call () aufgerufen wird. `Tf.keras.layers.TimeDistributed``` ist jedoch, wenn die ouput_shape der in das Argument eingefügten Ebene als Instanz generiert wird (dh` .build () `oder` `.call ()` `. Versuchen Sie es vorher zu wissen `). tf.keras.layers``` bietet eine Methode namens .compute_output_shape () für einen solchen Fall. Soweit ich [Code] sehen kann (https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/keras/engine/base_layer.py/#L530), versuche ich zu erstellen, aber wenn es sich um eine benutzerdefinierte Ebene handelt `` NotImplementedError``` wird ohne erfolgreichen Build ausgelöst.

Lösung

Überschreiben Sie `.compute_output_shape ()`, wenn Sie eine benutzerdefinierte Ebene definieren, um output_shape explizit zu definieren.

class Linear(tf.keras.layers.Layer):
    def __init__(self, emb_dim, *args, **kwargs):
        super(Linear, self).__init__(*args, **kwargs)
        self.emb_dim = emb_dim
        self.dense = Dense(self.emb_dim)

    def call(self, x):
        return self.dense(x)

    def compute_output_shape(self, input_shape):
        output_shape = input_shape[0:-1] + [self.emb_dim]
        return output_shape

Wenn es sich um diese benutzerdefinierte Ebene handelt, funktioniert sie normal, auch wenn ich zu `` `tf.keras.layers.TimeDistributed``` gehe.

Recommended Posts

Vorsichtsmaßnahmen bei der Verwendung von tf.keras.layers.TimeDistributed für die benutzerdefinierte Ebene von tf.keras
Vorsichtsmaßnahmen bei Verwendung der for-Anweisung in Pandas
Vorsichtsmaßnahmen bei der Verwendung von Chainer
Vorsichtsmaßnahmen bei der Verwendung von Pit mit Python
Vorsichtsmaßnahmen bei der Verwendung der TextBlob-Merkmalsanalyse
Vorsichtsmaßnahmen bei der Verwendung von Codecs und Pandas
Vorsichtsmaßnahmen bei Verwendung der Funktion urllib.parse.quote
Vorsichtsmaßnahmen bei der Verwendung von Phantomjs aus Python
Vorsichtsmaßnahmen bei Verwendung von sechs mit Python 2.5
[Python, Multiprocessing] Verhalten für Ausnahmen bei Verwendung von Multiprocessing
Vorsichtsmaßnahmen bei Verwendung der Google Cloud-Bibliothek mit GAE / py
Vorsichtsmaßnahmen für cv2.cvtcolor
Empfohlenes benutzerdefiniertes Layer-Schreiben von tf.keras und Verhalten bei Variablennamen
Vorsichtsmaßnahmen bei Verwendung von sqlite3 von macOS Sierra (10.12) mit Multiprocessing
Code-Änderungsort bei kostenloser Verwendung von Plotly
Vorsichtsmaßnahmen bei der Berechnung mit Zeichenfolge für TmeStampType von PySpark