深度学习之图像分类ResNet50

此次采纳迁徙学习并微调。个别的倡议是:

应用事后训练的模型进行特征提取:应用小型数据集时,通常的做法是利用在雷同域中的较大数据集上训练的模型中学习的特色。这是通过实例化预训练的模型并在顶部增加齐全连贯的分类器来实现的。事后训练的模型是“解冻的”,训练过程中仅更新分类器的权重。在这种状况下,卷积根底提取了与每个图像关联的所有特色,而您刚刚训练了一个分类器,该分类器依据给定的提取特色集确定图像类。

对预训练模型进行微调:为了进一步提高性能,可能须要通过微调将预训练模型的顶层从新用于新的数据集。在这种状况下,您须要调整权重,以使模型学习到特定于数据集的高级性能。通常在训练数据集很大并且与训练前的模型十分类似的原始数据集十分类似时,倡议应用此技术。

ResNet50实战

官网示例代码用的二分类,猫狗分类。
另外迁徙学习应用的是MobileNet V2 model。

所以这次的更改无非就是更改一下分类层,和引入ResNet即可了。

环境筹备

可能有些没有用到!

from tensorflow.keras.applications import ResNet50from tensorflow.keras import layersfrom tensorflow.keras.layers import Dense, GlobalAveragePooling2Dfrom tensorflow.keras import Modelfrom tensorflow.keras.preprocessing.image import ImageDataGeneratorfrom tensorflow.keras.applications.resnet50 import preprocess_inputfrom tensorflow.keras.preprocessing import imagefrom tensorflow.keras.callbacks import EarlyStoppingfrom tensorflow.keras.optimizers import Adamimport tensorflow as tfimport matplotlib.pyplot as pltimport PILimport numpy as np

数据集

应用的是官网的花朵图像的分类。官网也很无语,图像分类用的是花朵图像,到迁徙学习的时候又换成了狗和猫的分类。

import pathlibdataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)data_dir = pathlib.Path(data_dir)

拆分数据集

batch_size = 32img_height = 180img_width = 180train_ds = tf.keras.preprocessing.image_dataset_from_directory(  data_dir,  validation_split=0.2,  subset="training",  seed=123,  image_size=(img_height, img_width),  batch_size=batch_size)val_ds = tf.keras.preprocessing.image_dataset_from_directory(  data_dir,  validation_split=0.2,  subset="validation",  seed=123,  image_size=(img_height, img_width),  batch_size=batch_size)class_names = train_ds.class_namesprint(class_names)AUTOTUNE = tf.data.AUTOTUNEtrain_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

查看数据集

plt.figure(figsize=(10, 10))for images, labels in train_ds.take(1):  for i in range(9):    ax = plt.subplot(3, 3, i + 1)    plt.imshow(images[i].numpy().astype("uint8"))    plt.title(class_names[labels[i]])    plt.axis("off")

定义model

data_augmentation = tf.keras.Sequential([  tf.keras.layers.experimental.preprocessing.RandomFlip('horizontal'),  tf.keras.layers.experimental.preprocessing.RandomRotation(0.2),])for image, _ in train_ds.take(1):  plt.figure(figsize=(10, 10))  first_image = image[0]  for i in range(9):    ax = plt.subplot(3, 3, i + 1)    augmented_image = data_augmentation(tf.expand_dims(first_image, 0))    plt.imshow(augmented_image[0] / 255)    plt.axis('off')base_model = ResNet50(include_top=False, weights='imagenet',input_shape=(180,180,3))base_model.trainable = Falseinputs = tf.keras.Input(shape=(180,180,3))x = data_augmentation(inputs)x = preprocess_input(x)x = base_model(x,training=False)print(base_model.output.shape)x = GlobalAveragePooling2D()(x)y = Dense(5, activation='softmax')(x) #final layer with softmax activationmodel = Model(inputs=inputs, outputs=y, name="ResNet50")model.summary()

编译模型

loss = tf.keras.losses.SparseCategoricalCrossentropy()metrics = tf.metrics.SparseCategoricalAccuracy()model.compile(optimizer='Adam', loss=loss, metrics=metrics)len(model.trainable_variables)

训练模型

history = model.fit(train_ds,                    epochs=10,                    validation_data=val_ds)

基本上就能达到92的准确率。
92/92 [==============================] - 19s 206ms/step - loss: 0.0186 - sparse_categorical_accuracy: 1.0000 - val_loss: 0.2470 - val_sparse_categorical_accuracy: 0.9292

微调迁徙学习模型

按理说数据量不大,微调可能给不了太大晋升。试一下就是了。

175层解冻后面100层

base_model.trainable = True# Let's take a look to see how many layers are in the base modelprint("Number of layers in the base model: ", len(base_model.layers))# Fine-tune from this layer onwardsfine_tune_at = 100# Freeze all the layers before the `fine_tune_at` layerfor layer in base_model.layers[:fine_tune_at]:  layer.trainable = False

从新编译模型和训练模型

从未微调的最初一次训练接着训练10个epochs。

loss = tf.keras.losses.SparseCategoricalCrossentropy()metrics = tf.metrics.SparseCategoricalAccuracy()model.compile(optimizer='Adam', loss=loss, metrics=metrics)len(model.trainable_variables)fine_tune_epochs = 10total_epochs =  10 + fine_tune_epochshistory_fine = model.fit(train_ds,                         epochs=total_epochs,                         initial_epoch=history.epoch[-1],                         validation_data=val_ds)

后果反而还升高了。
92/92 [==============================] - 31s 341ms/step - loss: 0.1780 - sparse_categorical_accuracy: 0.9440 - val_loss: 0.3261 - val_sparse_categorical_accuracy: 0.9183

预测下数据

image_batch,label_batch = val_ds.as_numpy_iterator().next()print(label_batch)predictions = model.predict_on_batch(image_batch)for i in range(0,predictions.shape[0]):  print(np.argmax(predictions[i]))  prediction = np.argmax(predictions[i])    if (prediction != label_batch[i]):    plt.figure(figsize=(10, 10))    plt.imshow(images[i].numpy().astype("uint8"))    plt.title(class_names[label_batch[i]] + "-" + class_names[prediction])    plt.show()

附录

  • 官网示例代码迁徙学习和微调
  • 官网示例代码图像分类