+-
深度学习之图像分类ResNet50学习
首页 专栏 tensorflow 文章详情
0

深度学习之图像分类ResNet50学习

小鸡 发布于 5 月 10 日

深度学习之图像分类ResNet50

此次采用迁移学习并微调。一般的建议是:

使用预先训练的模型进行特征提取:使用小型数据集时,通常的做法是利用在相同域中的较大数据集上训练的模型中学习的特征。这是通过实例化预训练的模型并在顶部添加完全连接的分类器来完成的。预先训练的模型是“冻结的”,训练过程中仅更新分类器的权重。在这种情况下,卷积基础提取了与每个图像关联的所有特征,而您刚刚训练了一个分类器,该分类器根据给定的提取特征集确定图像类。

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

ResNet50实战

官方示例代码用的二分类,猫狗分类。
另外迁移学习使用的是MobileNet V2 model。

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

环境准备

可能有些没有用到!

from tensorflow.keras.applications import ResNet50 from tensorflow.keras import layers from tensorflow.keras.layers import Dense, GlobalAveragePooling2D from tensorflow.keras import Model from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.applications.resnet50 import preprocess_input from tensorflow.keras.preprocessing import image from tensorflow.keras.callbacks import EarlyStopping from tensorflow.keras.optimizers import Adam import tensorflow as tf import matplotlib.pyplot as plt import PIL import numpy as np

数据集

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

import pathlib dataset_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 = 32 img_height = 180 img_width = 180 train_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_names print(class_names) AUTOTUNE = tf.data.AUTOTUNE train_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 = False inputs = 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 activation model = 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 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

重新编译模型和训练模型

从未微调的最后一次训练接着训练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 = 10 total_epochs = 10 + fine_tune_epochs history_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()

附录

官方示例代码迁移学习和微调 官方示例代码图像分类
tensorflow
阅读 55 发布于 5 月 10 日
收藏
分享
本作品系原创, 采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议
大数据学习笔记
记录自己对大数据学习的点滴
关注专栏
avatar
小鸡

1.01的365次方=37.8

206 声望
18 粉丝
关注作者
0 条评论
得票数 最新
提交评论
你知道吗?

注册登录
avatar
小鸡

1.01的365次方=37.8

206 声望
18 粉丝
关注作者
宣传栏
目录

深度学习之图像分类ResNet50

此次采用迁移学习并微调。一般的建议是:

使用预先训练的模型进行特征提取:使用小型数据集时,通常的做法是利用在相同域中的较大数据集上训练的模型中学习的特征。这是通过实例化预训练的模型并在顶部添加完全连接的分类器来完成的。预先训练的模型是“冻结的”,训练过程中仅更新分类器的权重。在这种情况下,卷积基础提取了与每个图像关联的所有特征,而您刚刚训练了一个分类器,该分类器根据给定的提取特征集确定图像类。

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

ResNet50实战

官方示例代码用的二分类,猫狗分类。
另外迁移学习使用的是MobileNet V2 model。

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

环境准备

可能有些没有用到!

from tensorflow.keras.applications import ResNet50 from tensorflow.keras import layers from tensorflow.keras.layers import Dense, GlobalAveragePooling2D from tensorflow.keras import Model from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.applications.resnet50 import preprocess_input from tensorflow.keras.preprocessing import image from tensorflow.keras.callbacks import EarlyStopping from tensorflow.keras.optimizers import Adam import tensorflow as tf import matplotlib.pyplot as plt import PIL import numpy as np

数据集

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

import pathlib dataset_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 = 32 img_height = 180 img_width = 180 train_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_names print(class_names) AUTOTUNE = tf.data.AUTOTUNE train_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 = False inputs = 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 activation model = 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 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

重新编译模型和训练模型

从未微调的最后一次训练接着训练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 = 10 total_epochs = 10 + fine_tune_epochs history_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()

附录

官方示例代码迁移学习和微调 官方示例代码图像分类