将keras中两层的输出相乘
Multiplying the output of two layers in keras
我正尝试在 keras 中使用这种设计实现一个神经网络:http://nlp.cs.rpi.edu/paper/AAAI15.pdf
该算法基本上具有三个输入。输入 2 和输入 3 乘以相同的权重矩阵 W1 以产生 O2 和 O3。输入 1 乘以 W2 产生 O1。然后,我们需要对 O1 * O2 和 O1 * O3 进行点积。
我正在尝试在 keras 中实现它。
我的第一个想法是使用 keras Graph
class 并使 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
class,它具有 dot
作为一种允许的合并类型。但是,Merge
class 的输入层必须传递给构造函数。因此,似乎没有办法将共享节点的输出放入 Merge
以将 Merge
添加到 Graph
。
如果我使用 Sequential
个容器,我可以将它们放入 Merge
。但是,那么就没有办法实现两个 Sequential
层需要共享相同的权重矩阵。
我考虑尝试将 O1、O2 和 O3 连接成一个向量作为输出层,然后在 objective 函数内进行乘法运算。但是,这需要 objective 函数来拆分其输入,这在 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')))
我遇到了类似的问题。我想出了一个解决方案,但还没有尝试。
对将 Input2 和 Input3 作为输入的序列模型 A 使用卷积层。这样,相同的卷积核将应用于 Input2 和 Input3,也就是相同的权重 W1。
将Input1作为另一个Sequential模型B的输入。
使用合并层合并 A 和 B 的输出。
点也可以通过合并层的自定义功能来完成。
你可以用这个
main_branch.add(合并([branch_1,branch_2],模式='dot'))
我正尝试在 keras 中使用这种设计实现一个神经网络:http://nlp.cs.rpi.edu/paper/AAAI15.pdf
该算法基本上具有三个输入。输入 2 和输入 3 乘以相同的权重矩阵 W1 以产生 O2 和 O3。输入 1 乘以 W2 产生 O1。然后,我们需要对 O1 * O2 和 O1 * O3 进行点积。
我正在尝试在 keras 中实现它。
我的第一个想法是使用 keras Graph
class 并使 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
class,它具有 dot
作为一种允许的合并类型。但是,Merge
class 的输入层必须传递给构造函数。因此,似乎没有办法将共享节点的输出放入 Merge
以将 Merge
添加到 Graph
。
如果我使用 Sequential
个容器,我可以将它们放入 Merge
。但是,那么就没有办法实现两个 Sequential
层需要共享相同的权重矩阵。
我考虑尝试将 O1、O2 和 O3 连接成一个向量作为输出层,然后在 objective 函数内进行乘法运算。但是,这需要 objective 函数来拆分其输入,这在 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')))
我遇到了类似的问题。我想出了一个解决方案,但还没有尝试。
对将 Input2 和 Input3 作为输入的序列模型 A 使用卷积层。这样,相同的卷积核将应用于 Input2 和 Input3,也就是相同的权重 W1。
将Input1作为另一个Sequential模型B的输入。
使用合并层合并 A 和 B 的输出。 点也可以通过合并层的自定义功能来完成。
你可以用这个
main_branch.add(合并([branch_1,branch_2],模式='dot'))