gpt4 book ai didi

python - 如何在 Keras 中重用 VGG19 进行图像分类?

转载 作者:太空狗 更新时间:2023-10-30 02:01:49 25 4
gpt4 key购买 nike

我目前正在尝试了解如何重用 VGG19(或其他架构)以改进我的小型图像分类模型。我将图像(在本例中为绘画)分为 3 类(比方说,15、16 和 17 世纪的绘画)。我有一个相当小的数据集,每类 1800 个训练示例,验证集中每类 250 个。

我有以下实现:

from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K
from keras.callbacks import ModelCheckpoint
from keras.regularizers import l2, l1
from keras.models import load_model

# set proper image ordering for TensorFlow
K.set_image_dim_ordering('th')

batch_size = 32

# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)

# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1./255)

# this is a generator that will read pictures found in
# subfolers of 'data/train', and indefinitely generate
# batches of augmented image data
train_generator = train_datagen.flow_from_directory(
'C://keras//train_set_paintings//', # this is the target directory
target_size=(150, 150), # all images will be resized to 150x150
batch_size=batch_size,
class_mode='categorical')

# this is a similar generator, for validation data
validation_generator = test_datagen.flow_from_directory(
'C://keras//validation_set_paintings//',
target_size=(150, 150),
batch_size=batch_size,
class_mode='categorical')

model = Sequential()

model.add(Conv2D(16, (3, 3), input_shape=(3, 150, 150)))
model.add(Activation('relu')) # also tried LeakyRelu, no improvments
model.add(MaxPooling2D(pool_size=(2, 3), data_format="channels_first"))

model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 3), data_format="channels_first"))

model.add(Flatten())
model.add(Dense(64, kernel_regularizer=l2(.01)))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(3))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy',
optimizer='adam', # also tried SGD, it doesn't perform as well as adam
metrics=['accuracy'])

fBestModel = 'best_model_final_paintings.h5'
best_model = ModelCheckpoint(fBestModel, verbose=0, save_best_only=True)

hist = model.fit_generator(
train_generator,
steps_per_epoch=2000 // batch_size,
epochs=100,
validation_data=validation_generator,
validation_steps=200 // batch_size,
callbacks=[best_model],
workers=8 # cpu generation is run in parallel to the gpu training
)

print("Maximum train accuracy:", max(hist.history["acc"]))
print("Maximum train accuracy on epoch:", hist.history["acc"].index(max(hist.history["acc"]))+1)

print("Maximum validation accuracy:", max(hist.history["val_acc"]))
print("Maximum validation accuracy on epoch:", hist.history["val_acc"].index(max(hist.history["val_acc"]))+1)

我设法在过度拟合方面保持相当平衡: enter image description here enter image description here

如果我使架构更深,如果我更严格地对其进行正则化,它要么会过度拟合,要么像疯了一样跳来跳去,甚至在某一时刻达到 100%: enter image description here

我也尝试过使用 BatchNormalization,但是模型几乎没有学习,它在训练集上的准确率不超过 50%。尝试使用和不使用丢弃。

除了过度改变架构之外,我正在寻找其他改进模型的方法。我看到的选项之一是重用现有架构及其权重并将其插入到我的模型中。但我找不到任何真实的例子来说明如何去做。我主要关注这篇博文: https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html

它谈到了重用 VGG19 来提高准确性,但并没有真正解释它是如何完成的。还有其他我可以效仿的例子吗?我将如何使其适应我当前的实现?我找到了一个完整的模型架构,但无法在我的硬件上运行它,因此我正在寻找一种方法来重用已经训练好的带有权重的模型,然后根据我的问题对其进行调整。

此外,我不理解博客在 VGG 部分中谈到的“瓶颈功能”背后的概念。如果有人能解释一下,我们会很高兴。

最佳答案

你绝对应该试试 Transfer Learning (链接是“迁移学习 Keras”的第一个 Google 结果,有很多关于该主题的教程)。本质上,TL 是对具有新分类层的大型数据集(即最常见的 Imagenet)进行预训练的网络的微调。背后的想法是,您希望保留在网络较低层学习到的所有好的特征(因为您的图像很可能也具有这些特征),并且只在这些特征之上学习一个新的分类器。这往往很有效,特别是如果您的数据集较小,不允许从头开始对网络进行全面训练(这也比全面训练快得多)

请注意,有多种方法可以进行 TL(我鼓励您研究该主题以找到最适合您的方法)。在我的应用程序中,我只是使用从 Imagenet 公共(public)检查点获取的权重初始化网络,删除最后一层并从那里训练所有内容(使用足够低的学习率,否则你会弄乱你的低级功能实际上想保留)。这种方法允许数据扩充。

另一种方法是使用瓶颈。在这种情况下,瓶颈(在其他情况下也称为嵌入)是您的输入样本之一在网络中某个深度级别的内部表示。换句话说,当网络的输出在 N 层后停止时,您可以看到 N 级的瓶颈。为什么这有用?因为您可以使用预训练网络预先计算所有样本的瓶颈,然后仅模拟网络最后一层的训练,而无需实际重新计算网络的所有(昂贵的)部分直到瓶颈点。

一个简化的例子

假设您有一个具有以下结构的网络:

in -> A -> B -> C -> D -> E -> out

其中 inout 是输入和输出层,另一个是您可能在网络中拥有的任何类型的层。假设您发现在某处发布了在 Imagenet 上预训练的网络检查点。 Imagenet 有 1000 个类,您不需要任何一个。因此,您将丢弃网络的最后一层(分类器)。然而,其他图层包含您要保留的功能。让 E 成为我们示例中的分类器层。

从您的数据集中获取样本,将它们提供给 in 并收集匹配的瓶颈值 作为层 D 的输出。您对数据集中的所有样本执行一次此操作。瓶颈集合是您将用于训练新分类器的新数据集。

您构建了一个具有以下结构的虚拟网络:

bottleneck_in -> E' -> out

您现在像往常一样训练这个网络,但不是从您的数据集中提供样本,而是从瓶颈数据集中提供匹配的瓶颈。请注意,这样做会保存从 AD 的所有层的计算,但这样您就不能在训练期间应用任何数据扩充 (当然,您仍然可以构建瓶颈,但您将有大量数据要存储)。

最后,要构建您的最终分类器,您的网络架构将是

in -> A -> B -> C -> D -> E' -> out

权重 AD 来自公共(public)检查点,权重 E' 来自您的训练。

关于python - 如何在 Keras 中重用 VGG19 进行图像分类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46150757/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com