【问题标题】:Global average pooling does not affect training speed全局平均池化不影响训练速度
【发布时间】:2020-09-05 10:01:58
【问题描述】:

据我了解,全球平均池化应该会提高训练速度。但由于某种原因,它没有。我用Horse Or Human dataset。这是我的代码:

from tensorflow.keras.preprocessing.image import ImageDataGenerator

target_size = (160, 160)
batch_size = 100

data_generator = ImageDataGenerator(
    zoom_range=0.1,
    shear_range=0.1,
    rotation_range=30,
    brightness_range=[0.8, 1.2],
    channel_shift_range=0.1,
    horizontal_flip=True,
)
train_generator = data_generator.flow_from_directory(
    'data/horse-or-human/train',
    class_mode='binary',
    target_size=target_size,
    batch_size=batch_size,
)
val_generator = data_generator.flow_from_directory(
    'data/horse-or-human/validation',
    class_mode='binary',
    target_size=target_size,
    batch_size=batch_size,
)
from tensorflow.keras.applications import VGG16
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.layers import *

base_model = VGG16(
    include_top=False,
    input_shape=(*target_size, 3)
)

for layer in base_model.layers:
    layer.trainable = False

layer = Flatten()(base_model.output)
layer = Dense(512, activation='relu')(layer)
out = Dense(1, activation='sigmoid')(layer)

model = Model(inputs=base_model.input, outputs=out)

model.compile(optimizer=Adam(lr=5e-6), loss='binary_crossentropy', metrics=['acc'])
history = model.fit(
    train_generator, 
    epochs=150,
    steps_per_epoch=len(train_generator), 
    validation_data=val_generator, 
    validation_steps=len(val_generator))

此模型的每个训练阶段大约需要 14 秒。可训练参数个数为 6,554,625。

base_model = VGG16(
    include_top=False,
    input_shape=(*target_size, 3)
)

for layer in base_model.layers:
    layer.trainable = False

layer = GlobalAvgPool2D()(base_model.output)
layer = Dense(512, activation='relu')(layer)
out = Dense(1, activation='sigmoid')(layer)

model = Model(inputs=base_model.input, outputs=out)
model.compile(optimizer=Adam(lr=5e-6), loss='binary_crossentropy', metrics=['acc'])

history = model.fit(
    train_generator, 
    epochs=150,
    steps_per_epoch=len(train_generator), 
    validation_data=val_generator, 
    validation_steps=len(val_generator))

此模型只有 263,169 个可训练参数。但是每个 epoch 的时间仍然在 14 秒左右。

我用更大的 target_size 和其他基本模型进行了尝试,但实施 GlobalAvgPool2D 前后的时间仍然相同。

请解释一下这种行为。

【问题讨论】:

    标签: python tensorflow machine-learning keras computer-vision


    【解决方案1】:

    这可能是由于:

    • 数据管道未优化(没有cachingprefetching),可能花费的时间最多,网络运行时间可以忽略不计。请参阅Better performance with tf.data APIAnalyze tf.data performance with the TF Profiler 了解更多信息。
    • GlobalAvgPool2dFlatten 之后的Dense 层使用优化的底层C/C++(例如OpenMPMKL-DNN、cuda 内核和许多其他取决于使用的设备)高度并行化(它基本上是一个批处理矩阵乘法) ,因此更大的矩阵乘法并不那么严重(至少在一定程度上)。
    • FlattenGlobalAvgPooling 快,因为它是单个 reshape 操作 (reshape(batch_size, -1)),因此可能会在此处获得由于较大的 Dense 而丢失的内容。

    更大 input_shape 可能会有所不同,因为 Dense 不适合内存(cuda 或 cpu 缓存),但我希望它的 I/O 受限于图像正在加载。

    【讨论】:

    • 是不是说如果你没有服务器的CPU和GPU就不能在项目中使用全局平均池化?正如我已经说过的,我尝试了不同的基本模型和input_shape,但模型的学习速度同样快,但第二个模型(带有 GlobalAvgPool2D 的模型)总是表现出较差的质量
    • 您应该使用GlobalAvgPooling 而不是Flatten。更少的参数(如您所指出的)因此更高的 GPU 和内存效率,稍微慢一点(如果有的话,总之不应该),允许不同大小的图像,因为池化是在每个通道的基础上完成的,这是恒定的宽度和高度也不重要。您应该查看您的数据加载管道并对其进行优化,因为 IMO 它可能是您 14s 运行时的最大贡献因素。目前你不能对FlattenGlobalAvgPool 说太多,因为数据加载需要大部分时间。
    • 关于准确性(我认为这就是您所说的质量) - 取决于模型,一些在设计时考虑到了AveragePooling(当前和更新的架构,如 Efficient Nets、MobileNets),较旧的(像很老的 VGG16 一样)是用 Flatten 创建的,因此使用它可能会表现得更好。通常,参数的巨大增长并不值得(如果有的话)更好的结果。
    猜你喜欢
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 2021-06-17
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    相关资源
    最近更新 更多