使用Keras进行大规模图像分类-vgg16微调-

⏱️约2分钟
分享:

1引言

我最近开始学习机器学习,并参加了图像分类比赛Kaggle 。 这次我将总结如何使用python keras1实现vgg16微调。

2关于数据

数据集如下。 我只有经验丰富的MNIST这样的数据集, MNIST这在ML教程中经常见到,所以我觉得这是一个非常大的数据集。

  • 班级:约15,000
  • 学习数据量:约120万个图像文件。超过300GB
  • 每个图像文件的大小:随文件而异。例如1,600 \ * 1,200
  • 测试数据:约120,000个文件

3实施

3.1学习数据

首先,我将向您展示整个代码。

python
1from keras.preprocessing.image import ImageDataGenerator
2from keras import optimizers
3from keras.applications.vgg16 import VGG16
4from keras.layers import Dense, Dropout, Flatten, Input, BatchNormalization
5from keras.models import Model, Sequential
6from keras.callbacks import ModelCheckpoint
7import numpy as np
8
9train_data_dir = "/train/"
10validation_data_dir = "/validation/"
11
12train_datagen = ImageDataGenerator(rescale=1. / 255)
13validation_datagen = ImageDataGenerator(rescale=1. / 255)
14
15img_width, img_height = 200, 150
16nb_train_samples = 915649
17nb_validation_samples = 302091
18epochs = 50
19batch_size = 64
20nb_category = 14951
21
22train_generator = train_datagen.flow_from_directory(
23 train_data_dir,
24 target_size=(img_width, img_height),
25 batch_size=batch_size,
26 class_mode="categorical")
27
28validation_generator = validation_datagen.flow_from_directory(
29 validation_data_dir,
30 target_size=(img_width, img_height),
31 batch_size=batch_size,
32 class_mode="categorical")
33
34# define input_tensor
35input_tensor = Input(shape=(img_width, img_height, 3))
36
37vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
38
39top_model = Sequential()
40top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
41top_model.add(Dense(256, activation='relu', kernel_initializer='he_normal'))
42top_model.add(BatchNormalization())
43top_model.add(Dropout(0.5))
44top_model.add(Dense(nb_category, activation='softmax'))
45
46# Connect vgg16 and top_model
47model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))
48
49# Fix layers
50for layer in model.layers[:15]:
51 layer.trainable = False
52
53optimizer = optimizers.rmsprop(lr=5e-7, decay=5e-5)
54model.compile(loss='categorical_crossentropy',
55 optimizer=optimizer,
56 metrics=['accuracy'])
57
58checkpoint_cb = ModelCheckpoint("snapshot/{epoch:03d}-{val_acc:.5f}.hdf5", save_best_only=True)
59
60model.fit_generator(
61 train_generator,
62 steps_per_epoch=nb_train_samples // batch_size,
63 epochs=epochs,
64 validation_data=validation_generator,
65 validation_steps=nb_validation_samples // batch_size,
66 callbacks=[checkpoint_cb])
67
68# Save the model
69model.save("model.h5")
70
71model.summary()

3.1.1学习大量数据

在大多数教程中,我们可以看到数据加载如下。

python
1(X_train, y_train), (X_test, y_test) = mnist.load_data()

但是,当您像这样处理大规模数据时,不可能将整个数据加载到内存中。 相反,您可以使用flow_from_directory函数加载数据2。 此功能在实时扩展数据的同时处理图像数据。

首先,您需要创建ImageDataGenerator

python
1train_datagen = ImageDataGenerator(rescale=1. / 255)
2validation_datagen = ImageDataGenerator(rescale=1. / 255)

此类在执行预处理时执行图像数据的批量生成。这次,只需重新缩放即可。 1/255用于将0-255到0-1的RGB值范围标准化。

接下来,读取数据

python
1train_generator = train_datagen.flow_from_directory(
2 train_data_dir,
3 target_size=(img_width, img_height),
4 batch_size=batch_size,
5 class_mode="categorical")
6
7validation_generator = validation_datagen.flow_from_directory(
8 validation_data_dir,
9 target_size=(img_width, img_height),
10 batch_size=batch_size,
11 class_mode="categorical")

由于是分类分类,因此将class_mode设置为categorical 。 此时,您必须注意文件夹结构。如下所示,您必须为要分类的每个类创建一个子文件夹。

javascript
1data/
2 train/
3 classA/
4 aaa.jpg
5 bbb.jpg
6 ...
7 classB/
8 ccc.jpg
9 ddd.jpg
10 ...
11
12 validation/
13 classA/
14 eee.jpg
15 fff.jpg
16 ...
17 classB/
18 ggg.jpg
19 hhh.jpg
20 ...

3.1.2使用vgg16模型

学习使用VGG16模型,可以搭配使用Keras

python
1# define input_tensor
2input_tensor = Input(shape=(img_width, img_height, 3))
3
4vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
5
6top_model = Sequential()
7top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
8top_model.add(Dense(256, activation='relu', kernel_initializer='he_normal'))
9top_model.add(BatchNormalization())
10top_model.add(Dropout(0.5))
11top_model.add(Dense(nb_category, activation='softmax'))
12
13# Connect vgg16 with top_model
14model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))
15
16# Fix layers
17for layer in model.layers[:15]:
18 layer.trainable = False
19
20optimizer = optimizers.rmsprop(lr=5e-7, decay=5e-5)
21model.compile(loss='categorical_crossentropy',
22 optimizer=optimizer,
23 metrics=['accuracy'])
24
25checkpoint_cb = ModelCheckpoint("snapshot/{epoch:03d}-{val_acc:.5f}.hdf5", save_best_only=True)
26
27model.fit_generator(
28 train_generator,
29 steps_per_epoch=nb_train_samples // batch_size,
30 epochs=epochs,
31 validation_data=validation_generator,
32 validation_steps=nb_validation_samples // batch_size,
33 callbacks=[checkpoint_cb])

首先,使用默认的vgg16模型。 此时,指定了输入数据集的大小。

python
1input_tensor = Input(shape=(img_width, img_height, 3))
2
3vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)

接下来,附加您自己的模型。 请注意,为了进行微调,必须将上述参数中的include_top设置为False

python
1top_model = Sequential()
2top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
3top_model.add(Dense(256, activation='relu', kernel_initializer='he_normal'))
4top_model.add(BatchNormalization())
5top_model.add(Dropout(0.5))
6top_model.add(Dense(nb_category, activation='softmax'))
7
8# Connect vgg16 with top_model
9model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))

老实说,我不完全了解此处指定的relu函数。 因此,我认为该模型的内容不是很有帮助。

接下来,固定重量。如果未指定,将从一开始就重新学习权重,但是这次将被固定。

python
1for layer in model.layers[:15]:
2 layer.trainable = False

编译模型。此时,请指定优化器。 这指定更新参数时要使用的算法。

python
1optimizer = optimizers.rmsprop(lr=5e-7, decay=5e-5)
2model.compile(loss='categorical_crossentropy',
3 optimizer=optimizer,
4 metrics=['accuracy'])

终于学习了。如果在回调中设置了ModelCheckpoint ,则可以保存中间结果。这不是强制性的。

python
1checkpoint_cb = ModelCheckpoint("snapshot/{epoch:03d}-{val_acc:.5f}.hdf5", save_best_only=True)
2
3model.fit_generator(
4 train_generator,
5 steps_per_epoch=nb_train_samples // batch_size,
6 epochs=epochs,
7 validation_data=validation_generator,
8 validation_steps=nb_validation_samples // batch_size,
9 callbacks=[checkpoint_cb])

3.2预测

python
1from keras.preprocessing.image import ImageDataGenerator
2from keras import optimizers
3from keras.applications.vgg16 import VGG16
4from keras.layers import Dense, Dropout, Flatten, Input, BatchNormalization
5from keras.models import Model, Sequential, load_model
6import pandas as pd
7import numpy as np
8import os
9from pandas import DataFrame
10
11test_data_dir = "/test/"
12
13test_datagen = ImageDataGenerator(rescale=1. / 255)
14
15img_width, img_height = 200, 150
16nb_test_samples = 115474
17batch_size = 1
18nb_category = 14951
19
20test_generator = test_datagen.flow_from_directory(
21 test_data_dir,
22 target_size=(img_width, img_height),
23 batch_size=batch_size,
24 class_mode=None,
25 shuffle=False)
26
27model = load_model("model.h5")
28
29pred = model.predict_generator(
30 test_generator,
31 steps=nb_test_samples,
32 verbose=1)

它与学习代码没有太大不同。同样,使用flow_from_directory读取数据,但要注意的是,即使对于测试数据(=未知类),也需要子文件夹。例如,在以下配置中,除非您将数据组织在子文件夹中,否则它将不起作用。

javascript
1data/
2 test/
3 sub/
4 aaa.jpg
5 bbb.jpg
6 ...

由于该类是未知的,因此将class_mode设置为None

4小结

  • 了解如何在Keras中使用vgg16。
  • 使用flow_from_directory加载大规模数据。
  • 请注意,您还需要用于预测的子文件夹。

5参考

Footnotes

  1. Keras Documentation

  2. Building powerful image classification models using very little data

分享:

相关文章

带有Flutter Android应用程序CI/CD
Guides

带有Flutter Android应用程序CI/CD

了解如何使用Flutter构建Android应用的CI/CD pipeline。基于GitHub Actions,不使用fastlane。

mark241
如何在Flutter中本地化应用
Guides

如何在Flutter中本地化应用

了解如何使用arb文件在Flutter中本地化应用程序。本文基于Flutter 2.0.1版本。

mark241
将Azure资源描述为ARM Template
Guides

将Azure资源描述为ARM Template

ARM Template是定义Azure资源的json文件。本文介绍如何高效创建ARM Template来部署新资源。

mark241