Was ist der Standard-Kernel-Initialisierer in tf.layers.conv2d und tf.layers.dense?

73

Das offizielle Tensorflow API-Dokument behauptet, dass der Parameter kernel_initializerstandardmäßig Nonefür tf.layers.conv2dund verwendet wird tf.layers.dense.

Beim Lesen des Layer-Tutorials ( https://www.tensorflow.org/tutorials/layers ) habe ich jedoch festgestellt, dass dieser Parameter nicht im Code festgelegt ist. Zum Beispiel:

# Convolutional Layer #1
conv1 = tf.layers.conv2d(
    inputs=input_layer,
    filters=32,
    kernel_size=[5, 5],
    padding="same",
    activation=tf.nn.relu)

Der Beispielcode aus dem Tutorial läuft fehlerfrei, daher ist der Standardcode meiner Meinung nach kernel_initializernicht None. Welcher Initialisierer wird also verwendet?

In einem anderen Code habe ich kernel_initializerdie Conv2d- und die dichten Ebenen nicht festgelegt , und alles war in Ordnung. Als ich jedoch versuchte, das kernel_initializerauf zu setzen tf.truncated_normal_initializer(stddev=0.1, dtype=tf.float32), bekam ich NaN-Fehler. Was geht hier vor sich? Kann jemand helfen?

daniszw
quelle
Vielleicht hat das NaN einen anderen Grund? Ich verwende kernel_initializer = tf.truncated_normal_initializer (stddev = 0,001, dtype = tf.float32) und es funktioniert wie erwartet.
JirkaV

Antworten:

105

Gute Frage! Es ist ein ziemlicher Trick, es herauszufinden!

  • Wie Sie sehen können, ist es nicht in dokumentiert tf.layers.conv2d
  • Wenn Sie sich die Definition der Funktion ansehen, sehen Sie, dass die Funktion Folgendes aufruft variable_scope.get_variable:

In Code:

self.kernel = vs.get_variable('kernel',
                                  shape=kernel_shape,
                                  initializer=self.kernel_initializer,
                                  regularizer=self.kernel_regularizer,
                                  trainable=True,
                                  dtype=self.dtype)

Nächster Schritt: Was macht der Variablenbereich, wenn der Initialisierer None ist?

Hier steht:

Wenn der Initialisierer None(der Standardwert) ist, wird der im Konstruktor übergebene Standardinitialisierer verwendet. Wenn das auch so ist None, verwenden wir eine neue glorot_uniform_initializer.

Die Antwort lautet also: Es wird das verwendet glorot_uniform_initializer

Der Vollständigkeit halber die Definition dieses Initialisierers:

Der Glorot Uniform Initialisierer, auch Xavier Uniform Initialisierer genannt. Es zieht Proben aus einer gleichförmigen Verteilung innerhalb von [limit, limit] wo limitist , sqrt(6 / (fan_in + fan_out)) wo fan_indie Anzahl von Eingabeeinheiten im Gewicht Tensor und fan_outist die Anzahl der Ausgabeeinheiten in dem Gewicht Tensor. Referenz: http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf

Bearbeiten: Das habe ich im Code und in der Dokumentation gefunden. Vielleicht können Sie überprüfen, ob die Initialisierung so aussieht, indem Sie die Gewichte bewerten!

rmeertens
quelle
1
Ich hatte die gleiche Frage. Basierend auf den Kernel-Graphen im Tensorboard scheinen die Kernel aus einer gleichmäßigen Verteilung heraus initialisiert worden zu sein.
EXP0
2

Laut diesem Kurs von Andrew Ng und der Xavier-Dokumentation sollten Sie, wenn Sie ReLU als Aktivierungsfunktion verwenden, den Standardgewichtungsinitialisierer (der Xavier-Uniform ist ) besser in Xavier normal ändern, indem Sie:

y = tf.layers.conv2d(x, kernel_initializer=tf.contrib.layers.xavier_initializer(uniform=False), )
xtluo
quelle
2
Das ist keras.initializers.glorot_normal(seed=None)oder einfach kernel_initializer= 'glorot_normal'drinnen Conv2D in Keras.
bit_scientist