sto cercando di attuare in KERAS neurale (ish) netto con questo motivo: http://nlp.cs.rpi.edu/paper/AAAI15.pdfMoltiplicando l'uscita di due strati in keras
L'algoritmo è, essenzialmente, tre ingressi. L'ingresso 2 e l'ingresso 3 vengono moltiplicati per la stessa matrice di peso W1 per produrre O2 e O3. L'ingresso 1 viene moltiplicato per W2 per produrre O1. Quindi, dobbiamo prendere il prodotto punto di O1 * O2 e O1 * O3.
Sto provando a implementarlo in keras.
Il mio primo pensiero è stato quello di utilizzare la classe keras Graph
e rendere W1 uno strato nodo condiviso con due ingressi e due uscite. Bene finora.
Si pone quindi il problema di come prelevare i prodotti punto di queste due uscite con O1.
ho cercato di definire una funzione personalizzata:
def layer_mult(X, Y):
return K.dot(X * K.transpose(Y))
Poi:
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"])
Il problema che si pone sulla compilazione, è che KERAS vuole solo per dare lo strato Lambda un ingresso:
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)
Ho pensato che un'alternativa potrebbe essere quella di utilizzare una classe Merge
, che ha dot
come tipo di unione consentita. Tuttavia, i livelli di input per una classe Merge
devono essere passati al costruttore. Quindi, non sembra essere un modo per ottenere gli output dal nodo condiviso nello Merge
per aggiungere lo Merge
allo Graph
.
Se si utilizzavano i contenitori Sequential
, è possibile inserire quelli nello Merge
. Ma non ci sarebbe un modo per implementare il fatto che i due layer Sequential
devono condividere la stessa matrice di peso.
Ho pensato di provare a concatenare O1, O2 e O3 insieme in un singolo vettore come livello di output e quindi fare la moltiplicazione all'interno di una funzione obiettivo. Ma ciò richiederebbe alla funzione obiettivo di dividere il suo input, che non sembra possibile in keras (le relative funzioni Theano non passano attraverso l'API di keras).
Qualcuno sa una soluzione?
EDIT:
ho pensato che avevo fatto qualche progresso, perché ho scoperto che shared_node
sta attuando dot
(anche se la sua non nella documentazione).
Così ho avuto modo:
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")
E ora l'errore è:
>>> 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')))
Se non l'hai già, mi piacerebbe suggerire la creazione di un problema github per questo (anche se non sono uno sviluppatore di Keras). Inoltre, per quanto riguarda (ab) usando lo strato Siamese per questo, producendo O1 due volte con una matrice di peso condivisa? –
Ciao, hai trovato la soluzione al tuo problema? – Bharat