Keras:如何将2个张量与动态形状连接起来?

时间:2019-01-15 17:39:34

标签: python tensorflow keras keras-layer

我有一个用例,需要在Keras中将2D张量连接到3D张量。 3D张量的尺寸是动态的(例如3D张量可以是形状为[batch_size, num_timesteps, num_features],的LSTM层的输出,其中batch_sizenum_timesteps是动态的)。

在使用3D张量进行“合并”操作之前,我已经使用RepeatVector来重复2D张量的值。

但是,就我而言,“合并”操作会引发错误(下面的错误详细信息)。我在下面共享了我要实现的操作的代表性代码以及错误。

我怀疑这里的问题是动态形状的RepeatVector。或者,我是否缺少更根本的东西?有没有办法我可以正确地做到这一点?

我正在使用Keras v2.1.6和Tensorflow后端v1.8.0。

import keras
from keras.layers import *
input_3D = Input(shape=(None,100,), dtype='int32', name='input_3D')
input_2D = Input(shape=(100,), dtype='int32', name='input_2D')
input_2D_repeat = RepeatVector(K.shape(input_3D)[1])(input_2D)
merged = merge([input_3D, input_2D_repeat], name="merged", mode='concat')

上面的代码为“合并”操作引发以下错误:

  

ValueError:“ concat”模式只能合并具有匹配输出的图层   连接轴以外的其他形状。图层形状:[(无,无,100),   (无,“,” 100)]

我可以看到input_3D中的第二维是None,但是input_2D_repeat中的第二维是tf.Tensor 'strided_slice:0' shape=() dtype=int32

我该如何解决?

1 个答案:

答案 0 :(得分:0)

编辑:

再次阅读问题和答案后,我认为发布的解决方案不正确。我认为您是要沿着要素轴而不是时间轴进行连接,而且我不确定K.shape(input_3D)[1]这样的张量值是否可以用作RepeatVector这样的层的参数。对于您的情况,我想我可能只想借助Lambda层来完成整个事情:

import keras
from keras.layers import Input, Lambda
import keras.backend as K

def repeat_and_concatenate(inputs):
    input_3D, input_2D = inputs
    # Repeat 2D vectors
    input_2D_repeat = K.tile(K.expand_dims(input_2D, 1), [1, K.shape(input_3D)[1], 1])
    # Concatenate feature-wise
    return K.concatenate([input_3D, input_2D_repeat], axis=-1)

input_3D = Input(shape=(None,100,), dtype='int32', name='input_3D')
input_2D = Input(shape=(50,), dtype='int32', name='input_2D')
merged = Lambda(repeat_and_concatenate)([input_3D, input_2D])
print(merged)
# Tensor("lambda_1/concat:0", shape=(?, ?, 150), dtype=int32)

下面的前答案很错误

您需要指定要沿“时间”轴连接(而不是默认值,即最后一个)。您可以这样做:

import keras
from keras.layers import *

input_3D = Input(shape=(None,100,), dtype='int32', name='input_3D')
input_2D = Input(shape=(100,), dtype='int32', name='input_2D')
input_2D_repeat = RepeatVector(K.shape(input_3D)[1])(input_2D)
merged = Concatenate(axis=1)([input_3D, input_2D_repeat])

或者这个:

import keras
from keras.layers import *

input_3D = Input(shape=(None,100,), dtype='int32', name='input_3D')
input_2D = Input(shape=(100,), dtype='int32', name='input_2D')
input_2D_repeat = RepeatVector(K.shape(input_3D)[1])(input_2D)
merged = concatenate([input_3D, input_2D_repeat], axis=1)