Keras:如何将 2 个张量与动态形状连接起来?
Keras: How to concatenate 2 tensors with dynamic shapes?
我有一个用例,我需要在 Keras 中将 2D 张量连接到 3D 张量。 3D 张量的维度是动态的(例如,3D 张量可以是形状为 [batch_size, num_timesteps, num_features],
的 LSTM 层的输出,其中 batch_size
和 num_timesteps
是动态的)。
我已经使用 RepeatVector
在对 3D 张量进行 "merge" 操作之前重复 2D 张量的值。
但是,在我的例子中,"merge" 操作会引发错误(错误详情如下)。我在下面分享了我要实现的操作的代表性代码以及错误。
我怀疑这里的问题是动态形状的 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')
以上代码针对 "merge" 操作抛出以下错误:
ValueError: "concat" mode can only merge layers with matching output
shapes except for the concat axis. Layer shapes: [(None, None, 100),
(None, , 100)]
我可以看到input_3D
中的二次元是None
,但是input_2D_repeat
中的二次元是tf.Tensor 'strided_slice:0' shape=() dtype=int32
。
我该如何解决这个问题?
编辑:
重新看了一遍问题和我的回答,我觉得我贴的解决方案不正确。我认为你的意思是沿着特征轴连接,而不是时间轴,而且我不确定像 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)
下面的前一个答案可能是错误的
您需要指定要沿 "time" 轴串联(而不是默认值,即最后一个)。你可以这样做:
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)
我有一个用例,我需要在 Keras 中将 2D 张量连接到 3D 张量。 3D 张量的维度是动态的(例如,3D 张量可以是形状为 [batch_size, num_timesteps, num_features],
的 LSTM 层的输出,其中 batch_size
和 num_timesteps
是动态的)。
我已经使用 RepeatVector
在对 3D 张量进行 "merge" 操作之前重复 2D 张量的值。
但是,在我的例子中,"merge" 操作会引发错误(错误详情如下)。我在下面分享了我要实现的操作的代表性代码以及错误。
我怀疑这里的问题是动态形状的 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')
以上代码针对 "merge" 操作抛出以下错误:
ValueError: "concat" mode can only merge layers with matching output shapes except for the concat axis. Layer shapes: [(None, None, 100), (None, , 100)]
我可以看到input_3D
中的二次元是None
,但是input_2D_repeat
中的二次元是tf.Tensor 'strided_slice:0' shape=() dtype=int32
。
我该如何解决这个问题?
编辑:
重新看了一遍问题和我的回答,我觉得我贴的解决方案不正确。我认为你的意思是沿着特征轴连接,而不是时间轴,而且我不确定像 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)
下面的前一个答案可能是错误的
您需要指定要沿 "time" 轴串联(而不是默认值,即最后一个)。你可以这样做:
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)