python 使用预训练模型后要使用的图层:何时添加全局平均池二维()

jm81lzqq  于 2022-12-10  发布在  Python
关注(0)|答案(3)|浏览(109)

我正在使用预训练的模型对图像进行分类。我的问题是在我的模型中使用预训练的模型结构后,我必须添加什么样的层,以及为什么这两种实现方式不同。具体来说:
考虑两个示例,一个使用cats and dogs数据集:
here是一个实现,关键点在于基础模型:

# Create the base model from the pre-trained model MobileNet V2
base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
                                               include_top=False,
                                               weights='imagenet')
base_model.trainable = False

在添加最终的tf.keras.layers.Dense(1)之前,冻结并添加GlobalAveragePooling 2D()。因此,模型结构如下所示:

model = tf.keras.Sequential([
  base_model,
  global_average_layer,
  prediction_layer
])

其等效于:

model = tf.keras.Sequential([
  base_model,
  tf.keras.layers.GlobalAveragePooling2D()
  tf.keras.layers.Dense(1)
])

因此,他们不仅添加了最终的dense(1)图层,还在之前添加了GlobalAveragePooling 2D()图层。
另一个使用tf flowers数据集:
在这个implementation中是不同的。没有添加一个全局平均池2D()。

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))
feature_extractor_layer.trainable = False

model = tf.keras.Sequential([
  feature_extractor_layer,
  layers.Dense(image_data.num_classes)
])

其中image_data.num_classes为5,表示不同的花卉分类。因此,在本例中,不添加GlobalAveragePooling 2D()图层。
我不明白这一点。为什么这是不同的?何时添加一个GlobalAveragePooling 2D()或没有?什么是更好的/我应该做什么?
我不确定原因是因为在一种情况下数据集cats and dogs是二元分类问题,而在另一种情况下是多类分类问题。或者区别是在一种情况下tf.keras.applications.MobileNetV2用于加载MobileNetV 2,而在另一种实现中hub.KerasLayer用于获取feature_extractor。当我检查第一种实现中的模型时:

我可以看到最后一层是一个relu激活层。
当我检查feature_extractor时:

model = tf.keras.Sequential([
  feature_extractor,
  tf.keras.layers.Dense(1)
])

model.summary()

输出如下:

也许原因还在于我不明白tf.keras.applications.MobileNetV2hub.KerasLayer之间的区别。hub.KerasLayer只是给了我特征提取器。我知道这一点,但我仍然认为我没有理解这两种方法之间的区别。
我无法检查feature_extractor本身的图层。因此feature_extractor.summary()或feature_extractor.layers不起作用。我如何检查这里的图层?我如何知道我是否应该添加GlobalAveragePooling 2D?

vcirk6k6

vcirk6k61#

摘要

为什么这是不同的?何时添加一个GlobalAveragePooling 2D()或不?什么是更好的/我应该做什么?
第一种情况下,它输出的4维Tensor是最后一个卷积层的原始输出。因此,你需要以某种方式将它们展平,在本例中,你使用的是GlobalAveragePooling 2D(但你可以使用任何其他策略)。我不知道哪个更好:这取决于您的问题,取决于hub.KerasLayer版本如何实现flatten,它们可能完全相同。也就是说,我只选择其中一个,然后继续:我看不出他们之间有很大的差别,

长答案:了解Keras实施

差异在于两个基本模型的输出:在Keras示例中,输出的形状为(bz, hh, ww, nf),其中bz是批量大小,hhww是模型中最后一个卷积层的高度和重量,nf是在该最后一层中应用的滤波器(或卷积)的数量。
因此:这将输出基础模型的最后卷积(或滤波器)的输出。
因此,您需要将这些输出(您可以将其视为图像)转换为(bz, n_feats)形状的矢量,其中n_feats是基础模型正在计算的特征数。转换完成后,您可以堆叠分类层(或任意数量的层),因为此时您已经拥有了矢量。
如何计算这个转换?一些常见的替代方法是取卷积输出的平均值或最大值(这会减小大小),或者您可以将它们重新整形为一行,或者添加更多的卷积层,直到您得到一个矢量作为输出(我强烈建议遵循通常的做法,如平均值或最大值)。
在第一个示例中,当调用tf.keras.applications.MobileNetV2时,您使用的是与去年相关的默认策略,因此,最后一个卷积层“按原样”:您可以使用param pooling修改此行为,如here

合并:include_top为False时用于特征提取的可选池模式。

  • None(默认)表示模型的输出将是最后一个卷积块的4DTensor输出。
  • avg意味着全局平均汇集将被应用于最后一个卷积块的输出,并且因此模型的输出将是2DTensor。
  • max表示将应用全局最大池。

总之,在第一个示例中,您在构建基础模型时没有明确告知如何处理最后一层,模型会不断返回4维Tensor,您可以立即使用平均池将其转换为向量,因此如果您告诉Keras这样做,您可以避免这种显式平均池:

# Create the base model from the pre-trained model MobileNet V2
base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
                                               include_top=False,
                                               pooling='avg', # Tell keras to average last layer
                                               weights='imagenet')
base_model.trainable = False

model = tf.keras.Sequential([
  base_model,
  # global_average_layer, -> not needed any more
  prediction_layer
])

TFHub实现

最后,当您使用TensorFlow Hub实现时,当您选择feature_vector版本的模型时,它已经实现了某种类型的池(我还没有找到如何实现的),以确保模型输出向量而不是4维Tensor。因此,您不需要显式添加层来转换它们,因为它已经完成了。
在我看来,我更喜欢Keras的实现,因为它给了你更多的自由来选择你想要的策略(事实上,你可以继续堆叠任何你想要的)。

bejyjqdl

bejyjqdl2#

假设有一个模型采用[1,208,208,3]个图像,并具有6个具有核[2,2,2,2,2,7]的池化层,这将导致在最后一个conv层中针对2048个过滤器的图像[1,1,1,2048]的特征列。
如果我们放松对输入图像的约束(这通常是对象检测模型的情况),而在大小为[1,104,208,3]的同一组汇集层图像之后,将产生[1,4,7,2024]的前最后汇集输出,并且[1,256,408,3]将产生[1,8,13,2048]。该Map将具有与原始[1,7,7,2048]大致相同的信息量,但是原始池化层将不产生具有[1,1,1,N]的特征列。这就是为什么我们切换到全局池化层。
简而言之,如果我们对输入图像大小没有严格的限制(并且在模型中的第一个操作时不调整图像大小),全局池层就很重要。

dly7yett

dly7yett3#

我认为模型“www.example.com“的输出差异https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/2是1d vector * batch_size,您无法对其应用Conv2D。
tf.keras.applications.MobileNetV2的输出可能更复杂,因此您有更多的能力来转换输出。

相关问题