【问题标题】:Issue with Keras backend flattenKeras 后端扁平化的问题
【发布时间】:2017-11-24 21:12:02
【问题描述】:

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

x 是

之后:

Keras.backend.flatten(x)

x 变为:shape=(?,) dtype=float32>

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

EDIT-1

如果我使用batch_flatten(下面的branch3x3branch5x5 是来自先前卷积的张量),我会得到 (?, ?):

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

第一个 Lambda 的结果是

第二个 Lambda 的结果是

EDIT-2

尝试batch_flatten,但在我构建模型输出时下游出现错误(使用reshape 而不是batch_flatten 似乎有效)。 branch3x3branch5x5:

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: 无法将类型对象转换为张量。内容:(无,32)。考虑将元素转换为支持的类型。

【问题讨论】:

  • 请在发布之前检查您的代码是否可执行。当代码错误时,很难重现错误。您调用 K.concatenate([v[0], v[1], v[2]], axis=3) 时只有两个输入 [branch3x3, branch5x5]
  • 另外,是否有理由使用 Lambda 层而不是 Keras 中实现的 ConcatenateFlatten 层?
  • 抱歉打错了。我的真实代码更长,所以在这里将其剥离以专注于主要问题。我正在使用 Lambda 层根据您在 stackoverflow.com/questions/45309236/… 中的建议创建模型(在这种情况下面临类似的问题)
  • 我已经编辑并添加了一个示例以使其清楚:)。请看看这是否适合你。

标签: tensorflow keras flatten


【解决方案1】:

来自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,) 的一维张量。这就是为什么您的新张量具有一维形状(?,)

如果要保留第一个维度,请使用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 似乎需要前一层的固定输出形状。所以来自batch_flatten 的动态形状(None, None) 将不起作用。

我能想到两个选择:

  1. 将手动计算的output_shape 提供给Lambda 层:
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 并计算其中的输出形状):
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)

我更喜欢后者,因为它使代码不那么混乱。还有,

  • 您可以将包裹K.concatenate()Lambda 层替换为Concatenate 层。
  • 记得将Input(shape=(4, 1)) 移出并在您的Model(inputs=...) 电话中提供。

【讨论】:

  • 非常感谢,将尝试 Flatten() 选项。使用reshape 似乎也有效:x = Lambda(lambda v: K.reshape(v, (-1, product_of_dimensions)))(x)
猜你喜欢
  • 2016-04-02
  • 1970-01-01
  • 2020-03-26
  • 1970-01-01
  • 2019-02-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-31
  • 1970-01-01
相关资源
最近更新 更多