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?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie diese
main_branch.hinzufügen(Merge([branch_1, branch_2], Modus = 'dot'))
Ich stehe vor dem ähnlichen problem. Ich denke eine Lösung, aber nicht versuchen es noch.
Mithilfe von Convolution-Schichten für die Sequenzielle Modell, die beide Input2 und Input3 wie die Eingabe. Auf diese Weise gleichen convolution kernel wird angewendet, um Input2 ein Input3, aka das gleiche Gewicht W1.
Unter Input1 als Eingabe für ein weiteres Sequentielles Modell B.
Einen Merge-Layer zum Zusammenführen der Ausgabe von A und B.
Und den Punkt kann man auch über die custom-Funktion einer merge-Schicht.
TypeError
sagt, dass die Ausgabe tensor hat eine Keras tensor.