Multiplicando a produção de duas camadas em keras

votos
6

Eu estou tentando implementar em keras uma rede neural (ish) com este projeto: http://nlp.cs.rpi.edu/paper/AAAI15.pdf

O algoritmo tem, essencialmente, três entradas. A entrada 2 e 3 de entrada se multiplicado pela mesma matriz W1 peso para produzir O2 e O3. Entrada 1 fica multiplicado por W2 para produzir O1. Então, precisamos tomar o produto do ponto de O1 * O2, e O1 * O3.

Eu estou tentando implementar isso em keras.

Meu primeiro pensamento era usar o keras Graphclasse e fazer W1 uma camada nó compartilhado com duas entradas e duas saídas. Bem até agora.

O problema levanta-se então de como tirar os produtos de ponto de essas duas saídas com O1.

Tentei definir uma função personalizada:

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

Então:

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])

O problema que se coloca na compilação, é que keras só quer para dar a camada de Lambda uma entrada:

   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)

Eu pensei que uma alternativa seria usar uma Mergeclasse, que tem dotcomo um tipo de fusão permitido. Mas, as camadas de entrada para uma Mergeclasse tem que ser passado para o construtor. Assim, não parece ser uma forma de obter as saídas a partir do nó compartilhada no Mergepara adicionar o Mergeao Graph.

Se estava utilizando Sequentialrecipientes, que poderia alimentar aqueles em o Merge. Mas, então não seria uma maneira de implementar que as duas Sequentialcamadas precisam compartilhar a mesma matriz de peso.

Eu pensei sobre tentando concatenar O1, O2, O3 e juntos em um único vetor como uma camada de saída e, em seguida, fazer a multiplicação dentro de uma função objetiva. Mas, isso exigiria a função objetivo de dividir sua entrada, o que não parece ser possível em keras (as funções relevantes THEANO não são passados ​​para a API para keras).

Qualquer sabe uma solução?

EDITAR:

Eu pensei que eu tinha feito algum progresso, porque descobri que shared_nodeestá implementando dot(mesmo se não na documentação).

Então, eu tenho a:

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 agora o erro é:

>>> 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')))
Publicado 10/12/2015 em 02:22
fonte usuário
Em outras línguas...                            


2 respostas

votos
0

Eu estou enfrentando o problema similar. Eu acho que uma solução, mas não tentou isso ainda.

  1. Utilização de camadas de convolução para o modelo sequencial A, que leva tanto Entrada2 e Entrada3 como entrada. Desta forma, mesmo kernel de convolução será aplicada a input2 um Entrada3, aka o mesmo W1 peso.

  2. Tomando Input1 como a entrada de um outro modelo B. sequencial

  3. Usando uma camada Mesclar para mesclar a saída de A e B. E ponto também pode ser feito via função personalizada de uma camada de mesclagem.

Respondeu 07/05/2016 em 05:42
fonte usuário

votos
2

Você pode usar este

main_branch.add (Merge ([branch_1, branch_2], modo = 'dot'))

Respondeu 10/02/2017 em 09:25
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more