這次採用遷移學習並微調。通常的建議是:api
使用預先訓練的模型進行特徵提取:使用小型數據集時,一般的作法是利用在相同域中的較大數據集上訓練的模型中學習的特徵。這是經過實例化預訓練的模型並在頂部添加徹底鏈接的分類器來完成的。預先訓練的模型是「凍結的」,訓練過程當中僅更新分類器的權重。在這種狀況下,卷積基礎提取了與每一個圖像關聯的全部特徵,而您剛剛訓練了一個分類器,該分類器根據給定的提取特徵集肯定圖像類。app
對預訓練模型進行微調:爲了進一步提升性能,可能須要經過微調將預訓練模型的頂層從新用於新的數據集。在這種狀況下,您須要調整權重,以使模型學習到特定於數據集的高級功能。一般在訓練數據集很大而且與訓練前的模型很是類似的原始數據集很是類似時,建議使用此技術。dom
官方示例代碼用的二分類,貓狗分類。
另外遷移學習使用的是MobileNet V2 model。性能
因此此次的更改無非就是更改一下分類層,和引入ResNet便可了。學習
可能有些沒有用到!fetch
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")
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
ui
按理說數據量不大,微調可能給不了太大提高。試一下就是了。this
175層凍結前面100層google
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()