数据集: flower_photos
- daisy: 633 张图片 雏菊
- dandelion: 898 张图片 蒲公英
- roses: 641 张图片 玫瑰
- sunflowers: 699 张图片 向日葵
- tulips: 799 张图片 郁金香
数据存储在本地磁盘,读取用的是 tf.keras.preprocessing.image_dataset_from_directory(),其中的 image_size 用作 image resize,batch_size 用作 batch
最初的 train_ds = train_ds.shuffle().cache().prefetch(),这样做的目标是缩小 IO blocking
上面是模型搭建的代码:
model = tf.keras.Sequential([tf.keras.layers.experimental.preprocessing.Rescaling(1. / 255),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(num_classes)
])
此处把 pixel 的 rescale 放进了 Sequential,当做模型搭建的一部分,有利于模型部署
callbacks 外面用到了 ReduceLROnPlateau,Tensorboard,EarlyStopping
上图是训练模型四次的 log 记录图,其中 val_acc 的区间在 [0.6499, 0.6785],这个是失常景象,所以训练进去的模型准确率是会存在稳定的
代码地址: https://github.com/MaoXianXin…,然而须要在如上图的中央 flower dataset 这个 commit 处开一个新分支,而后找到 3.py 这个脚本,就能反复上图的试验了
因为下面的试验,准确率才 [0.6499, 0.6785],咱们须要进行优化,第一个改良是增加 data augmentation,此处咱们间接在模型搭建环节增加,代码如下所示
model = tf.keras.Sequential([tf.keras.layers.experimental.preprocessing.Rescaling(1. / 255),
augmentation_dict[args.key],
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(num_classes)
])
augmentation_dict[args.key],这个就是增加的 data augmentation,此处咱们只增加单种,具体 data augmentation 品种如下所示
augmentation_dict = {'RandomFlip': tf.keras.layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical"),
'RandomRotation': tf.keras.layers.experimental.preprocessing.RandomRotation(0.2),
'RandomContrast': tf.keras.layers.experimental.preprocessing.RandomContrast(0.2),
'RandomZoom': tf.keras.layers.experimental.preprocessing.RandomZoom(height_factor=0.1, width_factor=0.1),
'RandomTranslation': tf.keras.layers.experimental.preprocessing.RandomTranslation(height_factor=0.1, width_factor=0.1),
'RandomCrop': tf.keras.layers.experimental.preprocessing.RandomCrop(img_height, img_width),
'RandomFlip_prob': RandomFlip_prob("horizontal_and_vertical"),
'RandomRotation_prob': RandomRotation_prob(0.2),
'RandomTranslation_prob': RandomTranslation_prob(height_factor=0.1, width_factor=0.1),
}
接下来咱们看下试验后果的 log 记录图
能够看到,val_acc 大于 0.6785 (未增加数据加强) 的有 RandomTranslation > RandomRotation_prob > RandomRotation > RandomFlip_prob = RandomFlip > RandomZoom > RandomTranslation_prob
从后果看来,数据加强是无效的,接下来咱们进行第二个改良,更换更强的网络模型,咱们这里抉择 MobileNetV2
这里咱们分两种状况进行试验,第一种是把 MobileNetV2 当做 feature extraction 来应用,这个要求咱们 freeze 模型的 卷积局部,只训练增加进去的 top-classifier 局部,上面上代码
data_augmentation = tf.keras.Sequential([augmentation_dict[args.key],
])
preprocess_input = tf.keras.applications.mobilenet_v2.preprocess_input
base_model = tf.keras.applications.MobileNetV2(input_shape=img_size,
include_top=False,
weights='imagenet')
base_model.trainable = False
inputs = tf.keras.Input(shape=img_size)
x = data_augmentation(inputs)
x = preprocess_input(x)
x = base_model(x, training=False)
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dropout(0.2)(x)
outputs = tf.keras.layers.Dense(num_classes)(x)
model = tf.keras.Model(inputs, outputs)
print(model.summary())
试验后果如下图所示
能够看到,准确率晋升很显著,从数据加强的 0.7316 晋升到了 0.8937,这次要得益于 pre-trained model 是在 ImageNet 大数据集上做过训练,提取到的特色泛化性更好
为了进一步晋升模型的准确率,咱们采纳第二种形式,对 pre-trained model 做 fine-tune,就是在第一种形式的根底上,咱们 unfreeze 局部卷积层,因为浅层的卷积提取的特色都是很根底的特色,意味着很通用,然而深层的卷积提取的特色都是和数据集高度相干的,这里咱们要解决的是 flower_photos,所以能够对深层的一部分卷积做训练,以进一步提高模型的准确率
上面上代码
data_augmentation = tf.keras.Sequential([augmentation_dict[args.key],
])
preprocess_input = tf.keras.applications.mobilenet_v2.preprocess_input
base_model = tf.keras.applications.MobileNetV2(input_shape=img_size,
include_top=False,
weights='imagenet')
base_model.trainable = True
# Let's take a look to see how many layers are in the base model
print("Number of layers in the base model:", len(base_model.layers))
# Fine-tune from this layer onwards
fine_tune_at = 100
# Freeze all the layers before the `fine_tune_at` layer
for layer in base_model.layers[:fine_tune_at]:
layer.trainable = False
inputs = tf.keras.Input(shape=img_size)
x = data_augmentation(inputs)
x = preprocess_input(x)
x = base_model(x, training=False)
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dropout(0.2)(x)
outputs = tf.keras.layers.Dense(num_classes)(x)
model = tf.keras.Model(inputs, outputs)
model.load_weights('./save_models')
print(model.summary())
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-4)
model.compile(
optimizer=optimizer,
loss=tf.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
K.set_value(model.optimizer.learning_rate, 1e-4)
这里有个特地须要留神的中央是 learning_rate 的设置,K.set_value(model.optimizer.learning_rate, 1e-4),这个中央还是我顺便查看了下 learning_rate 的 log 记录图才发现的不对劲
能够看到,进行 fine-tune 的话,模型准确率进一步晋升,从 0.8937 —> 0.9482
到此为止,咱们实现了在 flower_photos 数据集上 val_acc = 0.9482,下一步可能会用 RandAugment 或者 Semi-supervised 来晋升模型的泛化能力
代码地址: https://github.com/MaoXianXin…