Die Multiplikation der Ausgabe von zwei Schichten in keras

Ich versuche, umzusetzen in keras eine neuronale(ish) net mit diesem design: http://nlp.cs.rpi.edu/paper/AAAI15.pdf

Der Algorithmus hat im wesentlichen drei Eingänge. Eingang 2 und Eingang 3 zu bekommen, multipliziert mit dem gleichen Gewicht matrix W1 zu produzieren O2 und O3. Eingang 1 wird multipliziert mit W2 zu produzieren O1. Dann müssen wir das Skalarprodukt O1 * O2-und O1 * O3.

Ich versuche, diesen umzusetzen, in keras.

Mein Erster Gedanke war, mit keras Graph Klasse und machen W1 eine gemeinsame node-Ebene mit zwei Eingängen und zwei Ausgängen. Fein so weit.

Das problem stellt sich dann, wie man die dot-Produkte dieser beiden Ausgänge mit O1.

Ich versucht, eine benutzerdefinierte Funktion definieren:

   def layer_mult(X, Y):
       return K.dot(X * K.transpose(Y))

Dann:

ntm.add_node(Lambda(layer_mult, output_shape = (1,1)), name = "ls_pos", inputs = ["O1", "O2"])
ntm.add_node(Lambda(layer_mult, output_shape = (1,1)), name = "ls_neg", inputs = ["O1", "O3"])

Das problem, dass sich auf kompilieren, ist, dass keras will nur eben die Lambda-Ebene-Eingang:

   1045         func = types.FunctionType(func, globals())
   1046         if hasattr(self, 'previous'):
-> 1047             return func(self.previous.get_output(train))
   1048         else:
   1049             return func(self.input)

TypeError: layer_mult() takes exactly 2 arguments (1 given)

Dachte ich, eine alternative könnte die Verwendung einer Merge Klasse, die hat dot als eine Art der zulässigen Zusammenführen. Aber, die Eingabe-Layer für eine Merge - Klasse an den Konstruktor übergeben werden. Also, es scheint nicht ein Weg, um die Ausgänge aus dem gemeinsamen Knoten in die Merge zum hinzufügen von Merge zu den Graph.

Wenn ich mit Sequential Container, die ich ernähren könnten diejenigen, die in der Merge. Aber, dann gäbe es nicht eine Möglichkeit zu implementieren, dass die beiden Sequential Schichten teilen müssen das gleiche Gewicht-matrix.

Ich dachte über das versuchen, zu verketten, O1, O2 und O3 zusammen in einen einzelnen Vektor als output-Schicht und dann die Multiplikation innerhalb einer Zielfunktion. Aber das verlangen würde, dass die Objektive Funktion zum aufteilen der Eingabe, die nicht möglich zu sein scheint, in keras (die relevanten Theano Funktionen nicht bestanden-durch, um zu keras API).

Jeder weiß eine Lösung?

EDIT:

Dachte ich, dass ich einige Fortschritte gemacht, weil ich fand, dass shared_node ist die Umsetzung dot (auch wenn Ihr nicht in der Dokumentation).

Also ich habe:

ntm = Graph()
ntm.add_input(name='g', input_shape=(300,))  #  Vector of 300 units, normally distributed around zero
ntm.add_node([pretrained bit], name = "lt", input = "g") # 300 * 128, output = (,128)
n_docs = 1000
ntm.add_input("d_pos", input_shape = (n_docs,)) # (,n_docs)
ntm.add_input("d_neg", input_shape = (n_docs,)) # (,n_docs)

ntm.add_shared_node(Dense(128, activation = "softmax", 
#                      weights = pretrained_W1, 
                      W_constraint = unitnorm(), 
                      W_regularizer = l2(0.001)
                      ), name = "ld", 
                    inputs = ["d_pos", "d_neg"],  
                    outputs = ["ld_pos", "ld_neg"], 
                    merge_mode=None) # n_docs * 128, output = (,128) * 2
ntm.add_shared_node(ActivityRegularization(0,0),   #ActivityRegularization is being used as a passthrough - the function of the node is to dot* its inputs
                    name = "ls_pos", 
                    inputs = ["lt", "d_pos"], 
                    merge_mode = 'dot')  # output = (,1)
ntm.add_shared_node(ActivityRegularization(0,0), 
                    name = "ls_neg", 
                    inputs = ["lt", "d_neg"], 
                    merge_mode = 'dot')  # output = (,1)
ntm.add_shared_node(ActivityRegularization(0,0), 
                    name = "summed", 
                    inputs = ["ls_pos", "ls_neg"], 
                    merge_mode = 'sum') # output = (,1)
ntm.add_node(ThresholdedReLU(0.5), 
             input = "summed", name = "loss") # output = (,1)
ntm.add_output(name = "loss_out", 
               input= "loss")
def obj(X, Y):
    return K.sum(Y)
ntm.compile(loss = {'loss_out' : obj},  optimizer = "sgd")

Und jetzt ist der Fehler:

>>> ntm.compile(loss = {'loss_out' : obj},  optimizer = "sgd")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "build/bdist.macosx-10.5-x86_64/egg/keras/models.py", line 602, in compile
  File "build/bdist.macosx-10.5-x86_64/egg/keras/layers/advanced_activations.py", line 149, in get_output
  File "build/bdist.macosx-10.5-x86_64/egg/keras/layers/core.py", line 117, in get_input
  File "build/bdist.macosx-10.5-x86_64/egg/keras/layers/core.py", line 1334, in get_output
  File "build/bdist.macosx-10.5-x86_64/egg/keras/layers/core.py", line 1282, in get_output_sum
  File "build/bdist.macosx-10.5-x86_64/egg/keras/layers/core.py", line 1266, in get_output_at
  File "build/bdist.macosx-10.5-x86_64/egg/keras/layers/core.py", line 730, in get_output
  File "build/bdist.macosx-10.5-x86_64/egg/keras/layers/core.py", line 117, in get_input
  File "build/bdist.macosx-10.5-x86_64/egg/keras/layers/core.py", line 1340, in get_output
  File "build/bdist.macosx-10.5-x86_64/egg/keras/layers/core.py", line 1312, in get_output_dot
  File "/Volumes/home500/anaconda/envs/[-]/lib/python2.7/site-packages/theano/tensor/var.py", line 360, in dimshuffle
    pattern)
  File "/Volumes/home500/anaconda/envs/[-]/lib/python2.7/site-packages/theano/tensor/elemwise.py", line 164, in __init__
    (input_broadcastable, new_order))
ValueError: ('You cannot drop a non-broadcastable dimension.', ((False, False, False, False), (0, 'x')))
  • Wenn Sie nicht bereits haben, würde ich vorschlagen, die Schaffung eines github Problem für dieses (obwohl ich bin kein Keras Entwickler). Außerdem, was ist mit (ab)mit dem Siamesen-Ebene für diese, produzieren O1 zweimal mit einem gemeinsamen Gewicht-matrix?
  • Hallo, wollte Sie herausfinden, die Lösung für Ihr problem?
InformationsquelleAutor Bob | 2015-12-10
Schreibe einen Kommentar