了解tf.keras.Input中的形状?

Understand the shape in tf.keras.Input?

刚学tensorflow和keras。这是一个代码示例:

# Create a symbolic input
input = tf.keras.Input(shape=(2,), dtype=tf.float32)

# Do a calculation using is
result = 2*input + 1

# the result doesn't have a value
result

calc = tf.keras.Model(inputs=input, outputs=result)
print(calc(np.array([1,2,3,4])).numpy())
print(calc(2).numpy())

文档说形状:一个形状元组(整数),不包括批量大小。 例如,shape=(32,) 表示预期输入将是 32 维向量的批次。这个元组的元素可以是NoneNone 元素表示形状未知的维度。

但是在上面的代码中,两个打印行都有效。但对我来说,它们是 1D 个维度和 1 个标量。那么如何理解形状呢?

我很确定如果您要编译并尝试 fit 您的“模型”会失败,因为 'learn'.

没有任何东西

但是:对于2*input + 1这样的简单操作,形状是不相关的,因为模型不包含任何神经网络节点,所以它没有建立权重和偏差矩阵,这需要一个形状要知道。

所以你是对的,你不应该期望输入形状为 (2,) 的模型既不接受标量也不接受形状 (4,) 的向量 - 它不会,一次您已经添加了一些神经网络层,例如 keras.layers.Dense() 或类似的。

事情是 tf. keras.Input 产生符号张量或占位符。并且可以和TF操作一起使用。参见 source code:

  Note that even if eager execution is enabled,
  `Input` produces a symbolic tensor (i.e. a placeholder).
  This symbolic tensor can be used with other
  TensorFlow ops, as such:
  '''python
  x = Input(shape=(32,))
  y = tf.square(x)
  '''

这就是为什么这些打印行都有效的原因。


现在,这里有一些场景。在您的代码中,您可以设置 shape = [n] 其中 n > = 0,等级 01 分别是缩放器和矢量。但是,如果 n 不等于 x.shape[1],您将得到等级 2 或矩阵的错误。例如:

import tensorflow as tf 
import numpy as np 

# Create a symbolic input
input  = tf.keras.Input(shape=[0], dtype=tf.float32)
result = 2*input + 1 
calc   = tf.keras.Model(inputs=input, outputs=result)

print(calc(1).numpy())                     # scaler rank 0
print(calc(np.array([1,2,3,4])).numpy())   # vector rank 1
print(calc(np.array([[1,2,3,4]])).numpy()) # matrix rank 2 
3.0
[3. 5. 7. 9.]

ValueError: Input 0 is incompatible with layer model_2: 
expected shape=(None, 0), found shape=(1, 4)

为了解决这个问题,我们需要为形状参数设置一个准确的特征维度数,这里应该是 4.

# Create a symbolic input
input  = tf.keras.Input(shape=[4], dtype=tf.float32)
result = 2*input + 1 
calc   = tf.keras.Model(inputs=input, outputs=result)

print(calc(1).numpy())                     # scaler rank 0
print(calc(np.array([1,2,3,4])).numpy())   # vector rank 1
print(calc(np.array([[1,2,3,4]])).numpy()) # matrix rank 2 
3.0
[3. 5. 7. 9.]
[[3. 5. 7. 9.]]

这是一个有趣的事实,如果我们构建这个 calc 模型,其中 shape = [1] 带有标量或向量, 后跟 2D 矩阵,它不会对 2D 输入提出任何投诉,因为只有当模型没有首先构建时它才会引发错误。通过使用一些输入调用模型,模型的形状得到设置。

# Create a symbolic input
input  = tf.keras.Input(shape=[1], dtype=tf.float32)
result = 2*input + 1 
calc   = tf.keras.Model(inputs=input, outputs=result)

print(calc(1).numpy())                     # scaler rank 0
print(calc(np.array([1,2,3,4])).numpy())   # vector rank 1
print(calc(np.array([[1,2,3,4]])).numpy()) # matrix rank 2 
3.0
[[3.]
 [5.]
 [7.]
 [9.]]
[[3. 5. 7. 9.]]

但是 AFAIK,如果您构建具有可训练层的模型,就不可能像这样玩耍。在这种情况下,您需要确保 shape 与输入数据之间的形状匹配问题。例如:

x = tf.keras.Input(shape=[4])
y = tf.keras.layers.Dense(10)(x)
model = tf.keras.Model(x, y)

print(model(np.array([[1,2,3,4]])).numpy()) # (1, 4)
print(model(np.array([1,2,3,4])).numpy())   # (4,)
[[ 1.4779348  -1.8168153  -0.93788755 -1.4927139  -0.23618054  2.4305463
  -1.6176091   0.6640817  -1.648994    3.5819988 ]]

ValueError: Input 0 of layer dense_1 is incompatible with the layer: 
: expected min_ndim=2, found ndim=1. Full shape received: (4,)