wake-up-neo.com

TimeDistributed (Dense) vs. Dense in Keras - Gleiche Anzahl von Parametern

Ich baue ein Modell, das einen String in einen anderen String konvertiert, indem wiederkehrende Layer (GRUs) verwendet werden. Ich habe sowohl eine Dense- als auch eine TimeDistributed (Dense) -Schicht als vorletzte Schicht ausprobiert, aber ich verstehe den Unterschied zwischen den beiden bei der Verwendung von return_sequences = True nicht, zumal sie scheinbar die gleiche Anzahl von Parametern haben .

Mein vereinfachtes Modell ist das Folgende:

InputSize = 15
MaxLen = 64
HiddenSize = 16

inputs = keras.layers.Input(shape=(MaxLen, InputSize))
x = keras.layers.recurrent.GRU(HiddenSize, return_sequences=True)(inputs)
x = keras.layers.TimeDistributed(keras.layers.Dense(InputSize))(x)
predictions = keras.layers.Activation('softmax')(x)

Die Zusammenfassung des Netzwerks ist:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 64, 15)            0         
_________________________________________________________________
gru_1 (GRU)                  (None, 64, 16)            1536      
_________________________________________________________________
time_distributed_1 (TimeDist (None, 64, 15)            255       
_________________________________________________________________
activation_1 (Activation)    (None, 64, 15)            0         
=================================================================

Dies ist für mich sinnvoll, da ich unter TimeDistributed verstanden habe, dass zu allen Zeitpunkten dieselbe Schicht angewendet wird. Daher verfügt die dichte Schicht über 16 * 15 + 15 = 255 Parameter (Gewichtungen + Verzerrungen).

Wenn ich jedoch zu einer einfachen dichten Ebene wechsle:

inputs = keras.layers.Input(shape=(MaxLen, InputSize))
x = keras.layers.recurrent.GRU(HiddenSize, return_sequences=True)(inputs)
x = keras.layers.Dense(InputSize)(x)
predictions = keras.layers.Activation('softmax')(x)

Ich habe immer noch nur 255 Parameter:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 64, 15)            0         
_________________________________________________________________
gru_1 (GRU)                  (None, 64, 16)            1536      
_________________________________________________________________
dense_1 (Dense)              (None, 64, 15)            255       
_________________________________________________________________
activation_1 (Activation)    (None, 64, 15)            0         
=================================================================

Ich frage mich, ob dies so ist, weil Dense () nur die letzte Dimension in der Form verwendet und alles andere als eine chargenartige Dimension behandelt. Aber dann bin ich nicht mehr sicher, was der Unterschied zwischen Dense und TimeDistributed (Dense) ist.

Update Betrachten von https://github.com/fchollet/keras/blob/master/keras/layers/core.py Es scheint, dass Dense die letzte Dimension nur für die Größe verwendet:

def build(self, input_shape):
    assert len(input_shape) >= 2
    input_dim = input_shape[-1]

    self.kernel = self.add_weight(shape=(input_dim, self.units),

Es verwendet auch keras.dot, um die Gewichte anzuwenden:

def call(self, inputs):
    output = K.dot(inputs, self.kernel)

Die Dokumente von keras.dot deuten an, dass es bei n-dimensionalen Tensoren gut funktioniert. Ich frage mich, ob das genaue Verhalten bedeutet, dass Dense () bei jedem Zeitschritt aufgerufen wird. Wenn ja, bleibt die Frage, was TimeDistributed () in diesem Fall erreicht.

14
thon

TimeDistributedDense wendet während des Abrollens von GRU/LSTM-Zellen auf jeden Zeitschritt dieselbe Dichte an. Die Fehlerfunktion wird also zwischen der vorhergesagten Markierungssequenz und der tatsächlichen Markierungssequenz liegen. (Dies ist normalerweise die Voraussetzung für Sequenzmarkierungsprobleme).

Mit return_sequences = False wird die dichte Ebene jedoch nur einmal in der letzten Zelle angewendet. Dies ist normalerweise der Fall, wenn RNNs für ein Klassifizierungsproblem verwendet werden. Wenn return_sequences = True ist, wird der Dense-Layer genauso wie TimeDistributedDense auf jeden Zeitschritt angewendet.

Also für Ihr Modell sind beide gleich, aber wenn Sie Ihr zweites Modell in "return_sequences = False" ändern, wird der Dense nur in der letzten Zelle angewendet. Versuchen Sie es zu ändern, und das Modell wird als Fehler ausgegeben, da das Y dann die Größe [Batch_size, InputSize] hat, es ist keine Sequenz mehr, sondern eine vollständige Sequenz, um Probleme zu kennzeichnen. 

from keras.models import Sequential
from keras.layers import Dense, Activation, TimeDistributed
from keras.layers.recurrent import GRU
import numpy as np

InputSize = 15
MaxLen = 64
HiddenSize = 16

OutputSize = 8
n_samples = 1000

model1 = Sequential()
model1.add(GRU(HiddenSize, return_sequences=True, input_shape=(MaxLen, InputSize)))
model1.add(TimeDistributed(Dense(OutputSize)))
model1.add(Activation('softmax'))
model1.compile(loss='categorical_crossentropy', optimizer='rmsprop')


model2 = Sequential()
model2.add(GRU(HiddenSize, return_sequences=True, input_shape=(MaxLen, InputSize)))
model2.add(Dense(OutputSize))
model2.add(Activation('softmax'))
model2.compile(loss='categorical_crossentropy', optimizer='rmsprop')

model3 = Sequential()
model3.add(GRU(HiddenSize, return_sequences=False, input_shape=(MaxLen, InputSize)))
model3.add(Dense(OutputSize))
model3.add(Activation('softmax'))
model3.compile(loss='categorical_crossentropy', optimizer='rmsprop')

X = np.random.random([n_samples,MaxLen,InputSize])
Y1 = np.random.random([n_samples,MaxLen,OutputSize])
Y2 = np.random.random([n_samples, OutputSize])

model1.fit(X, Y1, batch_size=128, nb_Epoch=1)
model2.fit(X, Y1, batch_size=128, nb_Epoch=1)
model3.fit(X, Y2, batch_size=128, nb_Epoch=1)

print(model1.summary())
print(model2.summary())
print(model3.summary())

In der obigen Beispielarchitektur von Modell 1 und Modell 2 sind Muster (Sequenz-Sequenz-Modelle) und Modell 3 ist eine vollständige Sequenz zum Markieren des Modells.

8
mujjiga

Hier ist ein Code, der bestätigt, dass TimeDistirbuted(Dense(X)) mit Dense(X) identisch ist:

import numpy as np 
from keras.layers import Dense, TimeDistributed
import tensorflow as tf

X = np.array([ [[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9],
                [10, 11, 12]
               ],
               [[3, 1, 7],
                [8, 2, 5],
                [11, 10, 4],
                [9, 6, 12]
               ]
              ]).astype(np.float32)
print(X.shape)

(2, 4, 3)

dense_weights = np.array([[0.1, 0.2, 0.3, 0.4, 0.5],
                          [0.2, 0.7, 0.9, 0.1, 0.2],
                          [0.1, 0.8, 0.6, 0.2, 0.4]])
bias = np.array([0.1, 0.3, 0.7, 0.8, 0.4])
print(dense_weights.shape)

(3, 5)

dense = Dense(input_dim=3, units=5, weights=[dense_weights, bias])
input_tensor = tf.Variable(X, name='inputX')
output_tensor1 = dense(input_tensor)
output_tensor2 = TimeDistributed(dense)(input_tensor)
print(output_tensor1.shape)
print(output_tensor2.shape)

(2, 4, 5)

(2, & le;, 5)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    output1 = sess.run(output_tensor1)
    output2 = sess.run(output_tensor2)

print(output1 - output2)

Und der Unterschied ist:

[[[0. 0. 0. 0. 0.]
  [0. 0. 0. 0. 0.]
  [0. 0. 0. 0. 0.]
  [0. 0. 0. 0. 0.]]

 [[0. 0. 0. 0. 0.]
  [0. 0. 0. 0. 0.]
  [0. 0. 0. 0. 0.]
  [0. 0. 0. 0. 0.]]]
0
user263387