Keras后端问题变得扁平化

时间:2017-11-24 21:12:03

标签: tensorflow keras flatten

为什么Keras.backend.flatten没有显示正确的尺寸?我有以下内容:

x是< tf.Tensor'concat_8:0'shape =(?,4,8,62)dtype = float32>

后:

Keras.backend.flatten(x)

x变为:< tf.Tensor'Reshape_22:0' shape =(?,) dtype = float32>

为什么x不是形状=(?,4 * 8 * 62)

修改-1

我得到(?,?)如果我使用batch_flattenbranch3x3& branch5x5以下是先前卷积的张量):

x = Lambda(lambda v: K.concatenate([v[0], v[1]], axis=3))([branch3x3, branch5x5])
x = Lambda(lambda v: K.batch_flatten(v))(x)

第一个Lambda的结果是< tf.Tensor'lambda_144 / concat:0'形状=(?,4,8,62)dtype = float32>

第二个Lambda的结果是< tf.Tensor'lambda_157 /重塑:0'形状=(?,?)dtype = float32>

修改-2

尝试batch_flatten但在构建模型输出时获取下游错误(使用reshape代替batch_flatten似乎有效)。 branch3x3是< tf.Tensor'conv2d_202 / Elu:0'形状=(?,4,8,30)dtype = float32>,branch5x5是< tf.Tensor'conv2d_203 / Elu :0'形状=(?,4,8,32)dtype = float32>:

from keras import backend as K
x = Lambda(lambda v: K.concatenate([v[0], v[1]], axis=3))([branch3x3, branch5x5])
x = Lambda(lambda v: K.batch_flatten(v))(x)
y = Conv1D(filters=2, kernel_size=4)(Input(shape=(4, 1)))
y = Lambda(lambda v: K.batch_flatten(v))(y)
z = Lambda(lambda v: K.concatenate([v[0], v[1]], axis=1))([x, y])
output = Dense(32, kernel_initializer=TruncatedNormal(), activation='linear')(z)
cnn = Model(inputs=[m1, m2], outputs=output)

output语句导致kernel_initializer出现以下错误: TypeError:无法将类型对象转换为Tensor。内容:(无,32)。考虑将元素转换为支持的类型。

1 个答案:

答案 0 :(得分:2)

来自flatten的文档字符串:

def flatten(x):
    """Flatten a tensor.
    # Arguments
        x: A tensor or variable.
    # Returns
        A tensor, reshaped into 1-D
    """

因此它将形状(batch_size, 4, 8, 62)的张量转换为形状为(batch_size * 4 * 8 * 62,)的1-D张量。这就是为什么你的新张量具有一维形状(?,)

如果您想保留第一个尺寸,请使用batch_flatten

def batch_flatten(x):
    """Turn a nD tensor into a 2D tensor with same 0th dimension.
    In other words, it flattens each data samples of a batch.
    # Arguments
        x: A tensor or variable.
    # Returns
        A tensor.
    """

编辑:您会看到形状为(?, ?),因为形状是在运行时动态确定的。如果您输入numpy数组,则可以轻松验证形状是否正确。

input_tensor = Input(shape=(4, 8, 62))
x = Lambda(lambda v: K.batch_flatten(v))(input_tensor)
print(x)

Tensor("lambda_1/Reshape:0", shape=(?, ?), dtype=float32)

model = Model(input_tensor, x)
out = model.predict(np.random.rand(32, 4, 8, 62))
print(out.shape)

(32, 1984)

EDIT-2:

从错误消息中,TruncatedNormal似乎需要来自上一层的固定输出形状。因此,来自(None, None)的动态形状batch_flatten将无效。

我可以想到两个选择:

  1. output_shape图层提供手动计算的Lambda
  2. x = Lambda(lambda v: K.concatenate([v[0], v[1]], axis=3))([branch3x3, branch5x5])
    x_shape = (np.prod(K.int_shape(x)[1:]),)
    x = Lambda(lambda v: K.batch_flatten(v), output_shape=x_shape)(x)
    
    input_y = Input(shape=(4, 1))
    y = Conv1D(filters=2, kernel_size=4)(input_y)
    y_shape = (np.prod(K.int_shape(y)[1:]),)
    y = Lambda(lambda v: K.batch_flatten(v), output_shape=y_shape)(y)
    
    z = Lambda(lambda v: K.concatenate([v[0], v[1]], axis=1))([x, y])
    output = Dense(32, kernel_initializer=TruncatedNormal(), activation='linear')(z)
    cnn = Model(inputs=[m1, m2, input_y], outputs=output)
    
    1. 使用Flatten图层(调用batch_flatten并计算其中的输出形状):
    2. x = Concatenate(axis=3)([branch3x3, branch5x5])
      x = Flatten()(x)
      
      input_y = Input(shape=(4, 1))
      y = Conv1D(filters=2, kernel_size=4)(input_y)
      y = Flatten()(y)
      
      z = Concatenate(axis=1)([x, y])
      output = Dense(32, kernel_initializer=TruncatedNormal(), activation='linear')(z)
      cnn = Model(inputs=[m1, m2, input_y], outputs=output)
      

      我更喜欢后者,因为它使代码更简洁。此外,

      • 您可以将Lambda图层包裹K.concatenate()替换为Concatenate图层。
      • 请务必将Input(shape=(4, 1))移出并在Model(inputs=...)来电中提供。