2015-12-10 8 views
6

Ich versuche, in ein neuronales (ish) net mit diesem Entwurf zu implementieren Keras: http://nlp.cs.rpi.edu/paper/AAAI15.pdfMultipliziert man die Ausgabe von zwei Schichten in keras

Der Algorithmus hat im Wesentlichen drei Eingänge. Eingang 2 und Eingang 3 werden mit der gleichen Gewichtsmatrix W1 multipliziert, um O2 und O3 zu erzeugen. Eingang 1 wird mit W2 multipliziert, um O1 zu erzeugen. Dann müssen wir das Skalarprodukt von O1 * O2 und O1 * O3 nehmen.

Ich versuche, dies in Keras zu implementieren.

Mein erster Gedanke war die Keras Graph Klasse zu verwenden und W1 eine gemeinsame Knotenschicht mit zwei Eingängen und zwei Ausgängen zu machen. Gut so weit.

Das Problem tritt dann auf, wie man die Punktprodukte dieser zwei Ausgänge mit O1 nimmt.

ich versuchte, eine benutzerdefinierte Funktion zu 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 bei der Kompilierung entsteht, ist, dass Keras nur der Lambda-Schicht einen Eingang geben will:

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) 

Ich dachte, eine Alternative könnte eine Merge Klasse zu verwenden, die 01 hatals eine Art zulässiger Zusammenführung. Die Eingabeschichten für eine Merge Klasse müssen jedoch an den Konstruktor übergeben werden. Es scheint also keine Möglichkeit zu geben, die Ausgänge von dem gemeinsamen Knoten in den Merge zu bringen, um den Merge zu dem Graph hinzuzufügen.

Wenn ich Sequential Container verwendet habe, könnte ich diese in die Merge einspeisen. Aber dann würde es keine Möglichkeit geben zu implementieren, dass die zwei Sequential Schichten die gleiche Gewichtsmatrix teilen müssen.

Ich dachte darüber nach zu versuchen, O1, O2 und O3 zusammen in einen einzelnen Vektor als eine Ausgabeschicht zu verketten und dann die Multiplikation innerhalb einer Zielfunktion zu machen. Aber das würde erfordern, dass die Zielfunktion ihre Eingaben aufteilt, was in Keras nicht möglich zu sein scheint (die relevanten Theano-Funktionen werden nicht an keras API übergeben).

Jeder weiß eine Lösung?

EDIT:

Ich dachte, ich einige Fortschritte gemacht hatte, weil ich, dass shared_node gefunden setzt dot (auch wenn es nicht in der Dokumentation).

Also habe ich zu:

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'))) 
+0

Wenn Sie nicht bereits haben, würde ich eine Schaffung vorschlagen github-Problem dafür (obwohl ich kein Keras-Entwickler bin). Und was ist mit (ab) der Verwendung der siamesischen Schicht dafür, O1 zweimal mit einer gemeinsamen Gewichtsmatrix zu produzieren? –

+0

Hallo, hast du die Lösung für dein Problem gefunden? – Bharat

Antwort

2

Sie dieses

main_branch.add verwenden können (Merge ([branch_1, branch_2], mode = 'Punkt'))

+0

Ich akzeptiere die Antwort, damit die Leute nicht weiter kommentieren müssen. Es erwies sich als sehr einfach und Ihre Antwort ist ein Beispiel für eine Möglichkeit, dies zu tun. – Bob

+0

Ich versuche etwas ähnliches [bitte sehen Sie] (http://stackoverflow.com/questions/42297359/typeerror-output-tensors-to-a-model-must-be-keras-tensors), aber es einfach nicht Arbeit. Ich versuche nur, einen Tensor mit einem Skalar zu multiplizieren. – displayname

0

ich ähnliches Problem konfrontiert bin. Ich denke eine Lösung aus, habe es aber noch nicht versucht.

  1. Verwenden von Faltungsschichten für sequenzielles Modell A, das sowohl Input2 als auch Input3 als Eingabe verwendet.Auf diese Weise wird der gleiche Faltungskern auf Input2 und Input3, das gleiche Gewicht W1, angewandt.

  2. Unter Input1 als Eingang eines anderen Modells Sequential B.

  3. eine Merge Schicht unter Verwendung der Ausgabe aus A und B. und Punkt-fusionieren kann auch über individuelle Funktion einer Verschmelzungsschicht durchgeführt werden.

+0

Ich versuche das derzeit (siehe [hier] (http://stackoverflow.com/questions/42297359/typeerror-output-tensors-to-a-model-must-be-keras-tensors)), aber es funktioniert nicht als Ich bekomme einen 'TypeError', der besagt, dass der Ausgangstensor ein Keras-Tensor sein muss. – displayname