了解 hub.KerasLayer 的 input_shape 参数

Understanding the input_shape parameter of hub.KerasLayer

迁移学习完成后,可以使用来自 tf hub 的模型。像 MobilNetV2 或 Inception。这些模型需要输入,即一定尺寸的图像。所以在应用模型之前必须将图像调整为这个大小。在此 tutorial 中使用以下内容:

feature_extractor_url = "https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/2" 

feature_extractor_layer = hub.KerasLayer(feature_extractor_url,
                                         input_shape=(224,224,3))

在此示例中,图像之前已调整为 224,224。我想知道 input_shape=(224,224,3)。在此 tutorial 中,预训练模型未加载 hub-KerasLayer,而是使用

base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
                                               include_top=False,
                                               weights='imagenet')

其中 IMG_SHAPE 是

IMG_SHAPE = (IMG_SIZE, IMG_SIZE, 3)

和img_size是160。所以这里的input_shape是input_shape=(160,160,3).

现在回到:

feature_extractor_layer = hub.KerasLayer(feature_extractor_url,
                                         input_shape=(224,224,3))

我想知道 input_shape 参数到底告诉我什么或做什么?所以我不需要在这里输入224,224,对吧?我可以输入另一个尺寸,比如 160,因为我的图像被调整到了这个尺寸?所以 MobilNetV2 确实期望 224,224,但是使用这个选项我可以指定其他内容吗?对于 tf.keras.applications.MobileNetV2,我找到了 documentation 的确切解释:

Optional shape tuple, to be specified if you would like to use a model with an input image resolution that is not (224, 224, 3). It should have exactly 3 inputs channels (224, 224, 3). You can also omit this option if you would like to infer input_shape from an input_tensor. If you choose to include both input_tensor and input_shape then input_shape will be used if they match, if the shapes do not match then we will throw an error. E.g. (160, 160, 3) would be one valid value.

所以当我将图像调整为 300,300 并且我想使用 MobileNetV2 时,我可以使用以下代码吗:

 feature_extractor_url = "https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/2" 
    
    feature_extractor_layer = hub.KerasLayer(feature_extractor_url,
                                             input_shape=(300,300,3))

或者我是否必须将大小调整为 224,224 并在此处输入 224,224?

当我检查 implementation 开始时,图像大小调整为 299,299,然后使用以下代码:

IMAGE_RES = 299

feature_extractor = hub.KerasLayer(URL,
  input_shape=(IMAGE_RES, IMAGE_RES, 3),
  trainable=False)

有必要精确到299吗?或者我也可以调整到另一个大小,比如 250 并将其作为输入:

   IMAGE_RES = 250

feature_extractor = hub.KerasLayer(URL,
  input_shape=(IMAGE_RES, IMAGE_RES, 3),
  trainable=False)

因此,预训练模型确实需要一定的固定大小,而这个 input_shape 参数的存在是为了使其灵活,以防用户想要使用其他大小,对吗?但是为什么所有这些例子都调整到模型假设的大小呢?我也可以把它做成另一个尺寸,对吧?所以在所有的例子中,它都说像模型期望的那样,我以这样的方式理解它,因此我们必须调整大小以完全符合模型的期望。但是 input_shape 参数正是为此而存在的,以使其具有灵活性,这样我就不必将大小调整为模型所期望的大小,而只需将大小调整为我想要的大小,并使用 input_shape 参数 I告诉模特这个?如上述示例中的 160 图像大小。或者,如果我使用 tf.keras.applications.MobileNetV2 加载预训练模型,但使用 hub.KerasLayer 我不能这样做,这是否可能?

这是一个很好的观察。

TLDR,可以为 tf.keras.applicationsModels 传递不同的 Input Shapes 参数 include_top = False 但那是当我们将 tf.keras.applications 与参数 include_top = True 一起使用以及当我们使用 Tensorflow Hub.

Models 时,这是不可能的

详细说明:

Tensorflow Hub Documentation 指出

> The height and width dimensions are fixed to the expected size of
> input images. (Future work may remove that restriction for fully
> convolutional modules.)

这就是原因,如果我们传递 Image Shape 而不是预期形状,则会引发错误,

 Expected these arguments to match one of the following 4 option(s):
    
    Option 1:
      Positional arguments (4 total):
        * TensorSpec(shape=(None, 224, 224, 3), dtype=tf.float32, name='inputs')
        * True
        * False
        * TensorSpec(shape=(), dtype=tf.float32, name='batch_norm_momentum')
      Keyword arguments: {}
    
    Option 2:
      Positional arguments (4 total):
        * TensorSpec(shape=(None, 224, 224, 3), dtype=tf.float32, name='inputs')
        * True
        * True
        * TensorSpec(shape=(), dtype=tf.float32, name='batch_norm_momentum')
      Keyword arguments: {}
    
    Option 3:
      Positional arguments (4 total):
        * TensorSpec(shape=(None, 224, 224, 3), dtype=tf.float32, name='inputs')
        * False
        * True
        * TensorSpec(shape=(), dtype=tf.float32, name='batch_norm_momentum')
      Keyword arguments: {}
    
    Option 4:
      Positional arguments (4 total):
        * TensorSpec(shape=(None, 224, 224, 3), dtype=tf.float32, name='inputs')
        * False
        * False
        * TensorSpec(shape=(), dtype=tf.float32, name='batch_norm_momentum')
      Keyword arguments: {}

类似地,当我们在使用 tf.keras.applicationsPre-Trained Models 和参数时传递不同的 Input Shape 时, include_top = True (也包括顶部的密集层),它会引发错误,

ValueError: When setting `include_top=True` and loading `imagenet` 
weights, `input_shape` should be (224, 224, 3).

但是如果我们设置参数的值,include_top = False,同时使用 tf.keras.applications 中的 Pre-Trained ModelsInput_Shape可以是 flexible 即,对于 MobileNetV2,我们可以传递列表中的任何形状,[96, 128, 160, 192, 224]),对于像 ResNetVGGNet 这样的模型,我们可以传递任何 Input Shape.