我有一个用例,需要在Keras中将2D张量连接到3D张量。 3D张量的尺寸是动态的(例如3D张量可以是形状为[batch_size, num_timesteps, num_features],
的LSTM层的输出,其中batch_size
和num_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
。
我该如何解决?
答案 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)