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')))
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? –
Hallo, hast du die Lösung für dein Problem gefunden? – Bharat