iva*_*lan 4 python machine-learning image-processing deep-learning keras
我目前正在尝试了解如何重用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)
Run Code Online (Sandbox Code Playgroud)
如果我让架构变得更深,那么如果我更严格地规范它,或者在某一点上达到100%,那么它要么过度装配,要么像疯了一样跳来跳去:

我也尝试过使用BatchNormalization,但是模型几乎没有学到任何东西,它在训练集上没有达到50%以上.无论辍学还是辍学都试过.
我正在寻找其他方法来改进模型,而不是过多地改变架构.我看到的一个选项是重用现有架构及其权重并将其插入到我的模型中.但我找不到任何关于如何做的真实例子.我主要关注这篇博文:https: //blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html
它讨论了重复使用VGG19来提高准确性,但它并没有真正解释它是如何完成的.还有其他可以遵循的例子吗?我如何使其适应我目前的实施?我找到了一个完整的模型架构,但在我的硬件上运行它是不可能的,所以我正在寻找一种方法来重用已经训练过的模型和权重,然后根据我的问题进行调整.
此外,我不理解"瓶颈功能"背后的概念,博客在VGG部分谈到了这个概念.如果有人能够解释它会很高兴.
你一定要试试转学习(链接是第一个Google转换学习Keras的结果,有很多关于这个主题的教程).本质上,TL是对具有新分类层的一些大数据集(即最常见的Imagenet)预先训练的网络的微调.背后的想法是,您希望保留在网络较低级别学习的所有优秀功能(因为您的图像很可能也具有这些功能),并且只需在这些功能之上学习新的分类器.这往往效果很好,特别是如果您的小数据集不允许从头开始对网络进行全面培训(它也比完整培训快得多)
请注意,有几种方法可以做TL(我鼓励你研究这个主题以找到最适合你的方法).在我的应用程序中,我只是使用从Imagenet公共检查点获取的权重来启动网络,删除最后一层并从那里训练所有内容(学习率低,或者你会搞乱你的低级功能)实际上想要保持).这种方法允许数据增加.
另一种方法是使用瓶颈.在此上下文中,瓶颈(也称为嵌入在其他上下文中)是网络中某个深度级别的一个输入样本的内部表示.换句话说,你可以看到N级的瓶颈,因为网络的输出在N层之后停止了.为什么这有用?因为您可以使用预先训练的网络预先计算所有样本的瓶颈,然后仅模拟网络最后层的培训,而无需实际重新计算网络的所有(昂贵)部分直至瓶颈点.
假设您有一个具有以下结构的网络:
in -> A -> B -> C -> D -> E -> out
Run Code Online (Sandbox Code Playgroud)
其中in和out是输入和输出图层,另一个是网络中可能包含的任何类型的图层.我们还说你发现在Imagenet上预先培训过的网络检查点.Imagenet有1000个课程,你不需要这些课程.所以你将丢弃网络的最后一层(分类器).但是,其他图层包含您要保留的功能.让我们E在我们的例子中,分类层.
从数据集中获取样本,将它们提供给in并收集匹配的瓶颈值作为图层的输出D.对数据集中的所有样本执行此操作一次.瓶颈的集合是您将用于训练新的clssifier的新数据集.
您构建具有以下结构的虚拟网络:
bottleneck_in -> E' -> out
Run Code Online (Sandbox Code Playgroud)
现在,您可以像往常一样训练此网络,但不是从数据集中提取样本,而是从瓶颈数据集中提供匹配的瓶颈.请注意,这样做,你从保存所有层的计算A来D,但这样一来,你不能训练过程中应用的任何数据增强(当然你仍然可以做,建设中的瓶颈,但你有大量的数据存储) .
最后,要构建最终的分类器,您的网络架构将是
in -> A -> B -> C -> D -> E' -> out
Run Code Online (Sandbox Code Playgroud)
与权重A,以D公众的检查点和权重采取E'从你的训练造成.
| 归档时间: |
|
| 查看次数: |
1631 次 |
| 最近记录: |