2017-11-24 3 views
3

Warum zeigt Keras.backend.flatten nicht richtige Dimension? Ich habe folgende:Problem mit Keras Backend flatten

x ist < tf.Tensor 'concat_8: 0' shape = (?, 4, 8, 62) dtype = float32 >

After:

Keras.backend.flatten(x) 

x wird : < tf.Tensor 'Reshape_22: 0' shape = (?,) dtype = float32 >

Warum ist x nicht die Form = (?, 4 * 8 * 62)

EDIT-1

ich, wenn ich batch_flatten (branch3x3 & branch5x5 unten sind Tensoren aus früheren Faltungen) (?,?):

x = Lambda(lambda v: K.concatenate([v[0], v[1]], axis=3))([branch3x3, branch5x5]) 
x = Lambda(lambda v: K.batch_flatten(v))(x) 

Ergebnis ersten Lambda ist < tf .Tensor 'lambda_144/concat: 0' Form = (?, 4, 8, 62) dtype = float32>

Ergebnis des zweiten Lambdas ist < tf.Tensor 'lambda_157/Reshape: 0' shape = (?,?) Dtype = float32>

EDIT-2

batch_flatten versucht, aber stromabwärts einen Fehler, wenn ich die Modell-Ausgabe bauen (mit reshape anstelle von batch_flatten scheint zu funktionieren). branch3x3 ist < tf.Tensor 'conv2d_202/Elu: 0' Form = (?, 4, 8, 30) dtype = float32> und branch5x5 ist < tf.Tensor 'conv2d_203/Elu: 0' Form = (?, 4, 8, 32) dtype = float32>:

from keras import backend as K 
x = Lambda(lambda v: K.concatenate([v[0], v[1]], axis=3))([branch3x3, branch5x5]) 
x = Lambda(lambda v: K.batch_flatten(v))(x) 
y = Conv1D(filters=2, kernel_size=4)(Input(shape=(4, 1))) 
y = Lambda(lambda v: K.batch_flatten(v))(y) 
z = Lambda(lambda v: K.concatenate([v[0], v[1]], axis=1))([x, y]) 
output = Dense(32, kernel_initializer=TruncatedNormal(), activation='linear')(z) 
cnn = Model(inputs=[m1, m2], outputs=output) 

output die Anweisung führt zu dem folgenden Fehler für die kernel_initializer: Typeerror: Fehler Objekt vom Typ Tensor zu konvertieren. Inhalt: (Keine, 32). Erwägen Sie, Elemente auf einen unterstützten Typ zu übertragen.

+0

Bitte prüfen Sie, ob Ihr Code ausführbar ist, bevor Sie ihn veröffentlichen. Es ist schwierig, den Fehler zu reproduzieren, wenn der Code falsch ist. Sie rufen 'K.concatenate ([v [0], v [1], v [2]], axis = 3)' mit nur zwei Eingaben '[branch3x3, branch5x5]'. –

+0

Gibt es auch einen Grund, 'Lambda'-Layer anstelle der in Keras implementierten' Concatenate'- und 'Flatten'-Layer zu verwenden? –

+0

Sorry, das war ein Tippfehler. Mein wirklicher Code ist länger, also habe ich ihn hier weggelassen, um mich auf die Hauptprobleme zu konzentrieren. Ich benutze die Lambda-Ebene für die Erstellung des Modells auf der Grundlage Ihrer Beratung in https://stackoverflow.com/questions/45309236/keras-backend-modeling-issue (hatte ein ähnliches Problem wie in diesem Fall) – csankar69

Antwort

2

Vom docstring von flatten:

def flatten(x): 
    """Flatten a tensor. 
    # Arguments 
     x: A tensor or variable. 
    # Returns 
     A tensor, reshaped into 1-D 
    """ 

So stellt sich ein Tensor mit Form (batch_size, 4, 8, 62) in ein 1-D-Tensor mit Form (batch_size * 4 * 8 * 62,). Deshalb hat Ihr neuer Tensor eine 1-D-Form (?,).

Wenn Sie die erste Dimension behalten möchten, verwenden batch_flatten:

def batch_flatten(x): 
    """Turn a nD tensor into a 2D tensor with same 0th dimension. 
    In other words, it flattens each data samples of a batch. 
    # Arguments 
     x: A tensor or variable. 
    # Returns 
     A tensor. 
    """ 

EDIT: Sie sehen die Form ist (?, ?), weil die Form dynamisch zur Laufzeit bestimmt wird. Wenn Sie ein numerisches Array einspeisen, können Sie leicht überprüfen, ob die Form korrekt ist.

input_tensor = Input(shape=(4, 8, 62)) 
x = Lambda(lambda v: K.batch_flatten(v))(input_tensor) 
print(x) 

Tensor("lambda_1/Reshape:0", shape=(?, ?), dtype=float32) 

model = Model(input_tensor, x) 
out = model.predict(np.random.rand(32, 4, 8, 62)) 
print(out.shape) 

(32, 1984) 

EDIT-2:

aus der Fehlermeldung, es scheint, dass TruncatedNormal eine Ausgangsform von der vorherigen Schicht fixiert erfordert. Die dynamische Form (None, None) von batch_flatten wird nicht funktionieren.

kann ich von zwei Möglichkeiten denken:

  1. manuell output_shape die Lambda Schichten berechnet Provide:
x = Lambda(lambda v: K.concatenate([v[0], v[1]], axis=3))([branch3x3, branch5x5]) 
x_shape = (np.prod(K.int_shape(x)[1:]),) 
x = Lambda(lambda v: K.batch_flatten(v), output_shape=x_shape)(x) 

input_y = Input(shape=(4, 1)) 
y = Conv1D(filters=2, kernel_size=4)(input_y) 
y_shape = (np.prod(K.int_shape(y)[1:]),) 
y = Lambda(lambda v: K.batch_flatten(v), output_shape=y_shape)(y) 

z = Lambda(lambda v: K.concatenate([v[0], v[1]], axis=1))([x, y]) 
output = Dense(32, kernel_initializer=TruncatedNormal(), activation='linear')(z) 
cnn = Model(inputs=[m1, m2, input_y], outputs=output) 
  1. Verwenden Flatten Schicht (die ruft batch_flatten auf und berechnet die Ausgabeform darin:
x = Concatenate(axis=3)([branch3x3, branch5x5]) 
x = Flatten()(x) 

input_y = Input(shape=(4, 1)) 
y = Conv1D(filters=2, kernel_size=4)(input_y) 
y = Flatten()(y) 

z = Concatenate(axis=1)([x, y]) 
output = Dense(32, kernel_initializer=TruncatedNormal(), activation='linear')(z) 
cnn = Model(inputs=[m1, m2, input_y], outputs=output) 

Ich würde das letztere bevorzugen, da es den Code weniger überladen macht. Auch kann

  • Sie ersetzen die Lambda Schicht Einwickeln K.concatenate() mit einer Concatenate Schicht.
  • Denken Sie daran, die Input(shape=(4, 1)) zu verschieben und in Ihrem Model(inputs=...) Anruf bereitzustellen.
+1

Vielen Dank, probieren Sie die Option Flatten(). Die Verwendung von "Umformen" scheint ebenfalls zu funktionieren: "x = Lambda (Lambda v: K.reshape (v, (-1, Produkt_von_Abmessungen))) (x)" – csankar69

Verwandte Themen