我正在尝试为可以接受可变大小输入的图像分类实施FCNN。该模型使用TensorFlow后端在Keras中构建。
考虑以下玩具示例:
model = Sequential()
# width and height are None because we want to process images of variable size
# nb_channels is either 1 (grayscale) or 3 (rgb)
model.add(Convolution2D(32, 3, 3, input_shape=(nb_channels, None, None), border_mode='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(32, 3, 3, border_mode='same'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(16, 1, 1))
model.add(Activation('relu'))
model.add(Convolution2D(8, 1, 1))
model.add(Activation('relu'))
# reduce the number of dimensions to the number of classes
model.add(Convolution2D(nb_classses, 1, 1))
model.add(Activation('relu'))
# do global pooling to yield one value per class
model.add(GlobalAveragePooling2D())
model.add(Activation('softmax'))
此模型运行良好,但我遇到了性能问题。与固定大小的输入训练相比,对可变大小的图像进行训练需要不合理的长时间。如果我将所有图像的大小调整为数据集中的最大大小,则训练模型所需的时间远远少于对可变大小输入的训练。那么input_shape=(nb_channels, None, None)
是指定可变大小输入的正确方法吗?有没有办法缓解这个性能问题?
更新
对于具有3个类和灰度图像的模型, model.summary()
:
Layer (type) Output Shape Param # Connected to
====================================================================================================
convolution2d_1 (Convolution2D) (None, 32, None, None 320 convolution2d_input_1[0][0]
____________________________________________________________________________________________________
activation_1 (Activation) (None, 32, None, None 0 convolution2d_1[0][0]
____________________________________________________________________________________________________
maxpooling2d_1 (MaxPooling2D) (None, 32, None, None 0 activation_1[0][0]
____________________________________________________________________________________________________
convolution2d_2 (Convolution2D) (None, 32, None, None 9248 maxpooling2d_1[0][0]
____________________________________________________________________________________________________
maxpooling2d_2 (MaxPooling2D) (None, 32, None, None 0 convolution2d_2[0][0]
____________________________________________________________________________________________________
convolution2d_3 (Convolution2D) (None, 16, None, None 528 maxpooling2d_2[0][0]
____________________________________________________________________________________________________
activation_2 (Activation) (None, 16, None, None 0 convolution2d_3[0][0]
____________________________________________________________________________________________________
convolution2d_4 (Convolution2D) (None, 8, None, None) 136 activation_2[0][0]
____________________________________________________________________________________________________
activation_3 (Activation) (None, 8, None, None) 0 convolution2d_4[0][0]
____________________________________________________________________________________________________
convolution2d_5 (Convolution2D) (None, 3, None, None) 27 activation_3[0][0]
____________________________________________________________________________________________________
activation_4 (Activation) (None, 3, None, None) 0 convolution2d_5[0][0]
____________________________________________________________________________________________________
globalaveragepooling2d_1 (Global (None, 3) 0 activation_4[0][0]
____________________________________________________________________________________________________
activation_5 (Activation) (None, 3) 0 globalaveragepooling2d_1[0][0]
====================================================================================================
Total params: 10,259
Trainable params: 10,259
Non-trainable params: 0
答案 0 :(得分:1)
我认为@marcin-możejko在他的评论中可能有正确的答案。 它可能与刚刚修复的this bug有关。如果事情经常被编译,this patch可能会警告您。
因此,升级到tf-nightly-gpu-2.0-preview软件包可能会解决此问题。
此外,tf.keras
是否也会出现此问题。
如果我将所有图像调整为数据集中的最大大小,则训练模型所需的时间仍然比对可变大小输入进行训练所需的时间少得多
请注意,对于具有“相同”填充的基本卷积,除像素对齐方式以外,零填充应对输出具有“无”效果。
所以一种方法是在固定的尺寸列表上训练,并将零填充图像训练到这些尺寸。例如,以128x128、256x256、512x512的批次进行训练。如果您不能解决动态编译问题,则至少只能编译3次。这有点像有时会在序列模型中看到的二维“按序列长度存储桶”方法。
答案 1 :(得分:0)
不同大小的图像表示不同比例的相似事物的图像。如果比例尺上的差异很大,则随着图像尺寸的减小,类似物体的相对位置将从位于帧的中心向左上方偏移。所示的(简单)网络体系结构在空间上是感知的,因此,由于非常不同规模的数据不一致,因此模型收敛的速率降低是一致的。这种架构不太适合在不同或多个位置查找同一事物。
一定程度的剪切,旋转,镜像将有助于模型泛化,但会重新缩放为一致的大小。因此,当您调整大小时,可以解决缩放问题,并使输入数据在空间上保持一致。
简而言之,我认为这种网络体系结构不适合/不适合您要执行的任务,即各种规模。