TensorFlow Specialization Course 2
Week1主要講了在數據集比較小的情況下很容易過擬合的問題。
Week2給出解決過擬合問題的一種解決方法:數據增強。
Week3主要講遷移學習,同時使用數據增強,另外介紹了另一種解決過擬合問題的方法:Dropout。
Week4主要講多分類問題,從二分類擴展到多分類。
多分類和二分類不同的地方有:
設置class_mode=‘categorical’。
tf.keras.layers.Dense(3, activation=‘softmax’) # 此處的3表示3種類別
設置loss=‘categorical_crossentropy’
每一週的內容都比較少,所以放在一起總結。
我們下面使用前三週所講的知識(遷移學習+數據增強+Dropout)來完成Kaggle比賽的狗貓分類。
下面代碼全部運行在Colab上。
導入必要的包
import os
import zipfile
import random
import tensorflow as tf
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from shutil import copyfile
下載數據集
!wget --no-check-certificate \
"https://download.microsoft.com/download/3/E/1/3E1C3F21-ECDB-4869-8368-6DEBA77B919F/kagglecatsanddogs_3367a.zip" \
-O "/tmp/cats-and-dogs.zip"
local_zip = '/tmp/cats-and-dogs.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('/tmp')
zip_ref.close()
print(len(os.listdir('/tmp/PetImages/Cat/')))
print(len(os.listdir('/tmp/PetImages/Dog/')))
# Expected Output:
# 12501
# 12501
try:
os.mkdir('/tmp/cats-v-dogs')
os.mkdir('/tmp/cats-v-dogs/training')
os.mkdir('/tmp/cats-v-dogs/testing')
os.mkdir('/tmp/cats-v-dogs/training/cats')
os.mkdir('/tmp/cats-v-dogs/training/dogs')
os.mkdir('/tmp/cats-v-dogs/testing/cats')
os.mkdir('/tmp/cats-v-dogs/testing/dogs')
except OSError:
pass
創建數據集目錄,下一步將圖像複製到對應文件夾中。需要注意的是,公開數據集中的數據並不是完美的,例如本次使用的數據集中存在文件大小爲空的圖像,需要把他們去除。
def split_data(SOURCE, TRAINING, TESTING, SPLIT_SIZE):
files = []
for filename in os.listdir(SOURCE):
file = SOURCE + filename
if os.path.getsize(file) > 0:
files.append(filename)
else:
print(filename + " is zero length, so ignoring.")
training_length = int(len(files) * SPLIT_SIZE)
testing_length = int(len(files) - training_length)
shuffled_set = random.sample(files, len(files))
training_set = shuffled_set[0:training_length]
testing_set = shuffled_set[-testing_length:]
for filename in training_set:
this_file = SOURCE + filename
destination = TRAINING + filename
copyfile(this_file, destination)
for filename in testing_set:
this_file = SOURCE + filename
destination = TESTING + filename
copyfile(this_file, destination)
CAT_SOURCE_DIR = "/tmp/PetImages/Cat/"
TRAINING_CATS_DIR = "/tmp/cats-v-dogs/training/cats/"
TESTING_CATS_DIR = "/tmp/cats-v-dogs/testing/cats/"
DOG_SOURCE_DIR = "/tmp/PetImages/Dog/"
TRAINING_DOGS_DIR = "/tmp/cats-v-dogs/training/dogs/"
TESTING_DOGS_DIR = "/tmp/cats-v-dogs/testing/dogs/"
split_size = .9
split_data(CAT_SOURCE_DIR, TRAINING_CATS_DIR, TESTING_CATS_DIR, split_size)
split_data(DOG_SOURCE_DIR, TRAINING_DOGS_DIR, TESTING_DOGS_DIR, split_size)
# Expected output
# 666.jpg is zero length, so ignoring
# 11702.jpg is zero length, so ignoring
使用遷移學習。
from tensorflow.keras import layers
from tensorflow.keras import Model
from tensorflow.keras.optimizers import RMSprop
!wget --no-check-certificate \
https://storage.googleapis.com/mledu-datasets/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5 \
-O /tmp/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5
from tensorflow.keras.applications.inception_v3 import InceptionV3
local_weights_file = '/tmp/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'
pre_trained_model = InceptionV3(input_shape=(150, 150, 3),
input_top=False, # False則表示只使用卷積層,去掉InceptionV3的全連接層
weights=None) # None爲隨機初始化 如選'imagenet'表示在ImageNet上預訓練的權重
# 載入我們下載好的預訓練權重
pre_trained_model.load_weights(local_weights_file)
# 先讓所有的卷積層凍結(參數不可訓練),因爲前面的卷積層的參數已經訓練好,我們不希望他們變化
for layer in pre_trained_model.layers:
layer.trainable = False
# pre_trained_model.summary()
# 可能最後幾層卷積層學習檢測的特徵也比較專門化,我們可以多棄幾層。比如下面我們直接使用mixed7層的輸出接我們的全連接層
last_layer = pre_trained_model.get_layer('mixed7')
print('last layer output shape: ', last_layer.output_shape)
last_output = last_layer.output
x = layers.Flatten()(last_output)
x = layers.Dense(1024, activation='relu')(x)
# 使用Dropout來防止過擬合。Dropout作用於上面的的層。
x = layers.Dropout(0.2)(x)
x = layers.Dense(1, activation='sigmoid')(x)
# Model這裏接受兩個參數 模型的輸入和輸出
model = Model(pre_trained_model.input, x)
model.compile(optimizer=RMSprop(lr=0.0001), loss='binary_crossentropy', metrics=['acc'])
和之前一樣使用ImageDataGenerator
訓練數據預處理,不同的是,我們在訓練集上使用數據增強來擴充數據集從而防止過擬合。在ImageDataGenerator
方法中添加數據增強的參數。
TRAINING_DIR = "/tmp/cats-v-dogs/training/"
# train_datagen = ImageDataGenerator(rescale=1./255.)
# 數據增強
train_datagen = ImageDataGenerator(
rescale=1./255.,
# 隨機旋轉圖像,角度取值範圍(0-180),
rotation_range=40,
# 上下或左右平移的範圍,0.2爲圖像大小的20%。
width_shift_range=0.2,
height_shift_range=0.2,
# 水平或垂直投影變換
shear_range=0.2,
# Randomly zooming inside pictures.
zoom_range=0.2,
# 水平翻轉
horizontal_flip=True,
# 用於填充旋轉或水平/垂直移動後填補像素 (什麼時候用?什麼時候不用?)
fill_mode='nearest')
train_generator = train_datagen.flow_from_directory(
TRAINING_DIR,
batch_size=100,
class_mode='binary',
target_size=(150, 150))
# 數據增強需要根據數據集特點來調整
# 例如之前的人-馬數據集中 人和馬都是直立着的。如果使用了圖像旋轉的方法,則驗證集的準確率比較低且波動很大。因爲驗證集中並沒有平躺的人或馬。
VALIDATION_DIR = "/tmp/cats-v-dogs/testing/"
validation_datagen = ImageDataGenerator(rescale=1.0/255.)
validation_generator = validation_datagen.flow_from_directory(VALIDATION_DIR,
batch_size=100,
class_mode='binary',
target_size=(150, 150))
# Expected Output:
# Found 22498 images belonging to 2 classes.
# Found 2500 images belonging to 2 classes.
開始訓練,將訓練的數據存入history。
history = model.fit_generator(train_generator,
epochs=50,
verbose=1,
validation_data=validation_generator)
可視化訓練過程中的loss和accuracy變化。
%matplotlib inline
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
acc=history.history['acc']
val_acc=history.history['val_acc']
loss=history.history['loss']
val_loss=history.history['val_loss']
epochs=range(len(acc)) # Get number of epochs
# 展示每一次迭代訓練集和驗證集的accuracy
plt.plot(epochs, acc, 'r', "Training Accuracy")
plt.plot(epochs, val_acc, 'b', "Validation Accuracy")
plt.title('Training and validation accuracy')
plt.figure()
# 展示每一次迭代訓練集和驗證集的loss
plt.plot(epochs, loss, 'r', "Training Loss")
plt.plot(epochs, val_loss, 'b', "Validation Loss")
plt.figure()
查看如何在colab上使用Kaggle API向Kaggle提交答案:https://blog.csdn.net/JSerenity/article/details/89713458
Kaggle鏈接:https://www.kaggle.com/c/dogs-vs-cats
參考:
<https://github.com/lmoroney/dlaicourse/blob/master/Course 2 - Part 6 - Lesson 3 - Notebook.ipynb