【问题标题】:Multiplying the output of two layers in keras将keras中两层的输出相乘
【发布时间】:2015-12-10 04:22:52
【问题描述】:

我正在尝试用这种设计在 keras 中实现一个神经网络:http://nlp.cs.rpi.edu/paper/AAAI15.pdf

该算法本质上具有三个输入。输入 2 和输入 3 乘以相同的权重矩阵 W1 以产生 O2 和 O3。输入 1 乘以 W2 得到 O1。然后,我们需要取 O1 * O2 和 O1 * O3 的点积。

我正在尝试在 keras 中实现这一点。

我的第一个想法是使用 keras Graph 类,并使 W1 成为具有两个输入和两个输出的共享节点层。到目前为止还好。

然后出现的问题是如何将这两个输出的点积与 O1 相乘。

我尝试定义一个自定义函数:

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

然后:

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

编译时出现的问题是,keras 只想给 Lambda 层一个输入:

   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)

我认为另一种选择可能是使用Merge 类,它具有dot 作为允许的合并类型。但是,Merge 类的输入层必须传递给构造函数。因此,似乎没有办法将共享节点的输出获取到Merge 以将Merge 添加到Graph

如果我使用Sequential 容器,我可以将它们输入Merge。但是,没有办法实现两个Sequential 层需要共享相同的权重矩阵。

我曾想过尝试将 O1、O2 和 O3 连接成一个向量作为输出层,然后在目标函数中进行乘法运算。但是,这需要目标函数拆分其输入,这在 keras 中似乎是不可能的(相关的 Theano 函数没有传递到 keras API)。

有人知道解决办法吗?

编辑:

我认为我已经取得了一些进展,因为我发现 shared_node 正在实现 dot(即使它不在文档中)。

所以我必须:

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

现在错误是:

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

【问题讨论】:

  • 如果您还没有,我建议为此创建一个 github 问题(尽管我不是 Keras 开发人员)。此外,如何(ab)为此使用 Siamese 层,使用共享权重矩阵生成两次 O1?
  • 嗨,您找到解决问题的方法了吗?

标签: python neural-network theano deep-learning keras


【解决方案1】:

你可以用这个

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

【讨论】:

  • 我接受这个答案,所以人们不需要继续对此发表评论。事实证明这很容易,您的回复就是其中一种方法的示例。
  • 我正在尝试类似please take a look 但它根本不起作用。我要做的就是将张量乘以标量。
【解决方案2】:

我面临着类似的问题。我想出了一个解决方案,但还没有尝试。

  1. 为顺序模型 A 使用卷积层,将 Input2 和 Input3 作为输入。这样,相同的卷积核将应用于 Input2 和 Input3,也就是相同的权重 W1。

  2. 将 Input1 作为另一个 Sequential 模型 B 的输入。

  3. 使用合并层合并 A 和 B 的输出。 点也可以通过合并层的自定义功能来完成。

【讨论】:

  • 我目前正在尝试这个(见here),但它不起作用,因为我得到一个TypeError,它说输出张量必须是Keras张量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-20
  • 1970-01-01
  • 2017-07-14
  • 1970-01-01
  • 1970-01-01
  • 2018-02-23
相关资源
最近更新 更多