在Keras中使用合并

时间:2017-09-20 11:44:10

标签: python keras

我在keras中有3个张量:

  • 形状的张量a(?,4)
  • 形状的张量b(?,4)
  • 形状的张量c(?, 2, 4)

其中?是批量大小。我想计算之间的余弦相似度:

  • ab以及
  • a以及c的每一行(本例中为2行)

要计算ab之间的差值,可以直接进行以下操作:

from keras.layers import Reshape, merge
cos_a_b = Reshape((1,))(merge([a, b], mode='cos', dot_axes=1))

输出格式为(?,1),符合预期。

但是我无法找到ac之间的cos相似性(哪个输出的格式应为(?, 2))。使用相同的merge函数(merge([a, c],mode='cos',dot_axes=1))我有错误

ValueError: Only layers of same output shape can be merged using cos mode. Layer shapes: [(None, 4), (None, 2, 4)]

知道如何完成它吗?

修改

关注blackplant的答案:

如果我执行以下操作:

c_rep = RepeatVector(2)(c)
cos_a_c = merge([a,c_rep],mode='cos', dot_axes=1)

我收到以下错误:

Only layers of same output shape can be merged using cos mode. Layer shapes: [(None, Dimension(2), 4), (None, 2, 4)]

但如果我这样做:

cos_a_c = merge([a, RepeatVector(2)(c)],mode='cos', dot_axes=1)

代码正常运行,但输出是形状(?, 1, 4, 4)的张量。

使用dot_axes=2输出的形状为(?,1, 2, 2)

不应该是(?,2)吗?

2 个答案:

答案 0 :(得分:1)

我不确定这种merge方法是否有详细记录。我更喜欢使用记录的图层并手动执行相似性。 Formula taken from Wikipedia

import keras.backend as K

def getDivisor(x):

    return K.sqrt(K.sum(K.square(x),axis=-1,keepdims=True))

def similarity(a, b): 

    dividend = K.sum(a*b,axis=-1,keepdims=True)
    return dividend / (getDivisor(a) * getDivisor(b))

现在,我们应该注意使ac的形状兼容。

abSim = Lambda(similarity, output_shape=(1,))([a,b])

aCompatible = Reshape((1,4))(a)
acSim = Lambda(similarity, output_shape=(2,1))([aCompatible,c])

Reshape((1,4))应用于a可能就足以与merge方法一起使用。但我无法确定。

答案 1 :(得分:0)

您是否尝试过使用RepeatVector?使用它你可以重复“a”张量并将其转换为形状(2,4)的张量,此时你可以将它与c合并。

# Repeat a twice
a_r = RepeatVector(2)(a)
merge([a_r, b], mode='cos', dot_axes=1) 

编辑:所以似乎不是重复'a'以便能够将它与'c'合并,而是应该拆分c并将点操作应用于每个切片。

# Select first row
c_0 = Lambda(lambda x: x[0,:], output_shape=(4,))(c)
# Compute cos between first row and a
merge([a, c_0], mode='cos', dot_axes=1)