貓狗數據集的兩階段分類

一、狗貓數據集的兩階段分類實驗

1、數據集下載

下載鏈接:貓狗數據集 提取碼:dmp4

2、分類

導入keras庫:

import keras
keras.__version__

在這裏插入圖片描述
圖片分類:要注意自己的數據集的存放位置以及輸出結果文件的存放位置

import os, shutil
# The path to the directory where the original
# dataset was uncompressed
original_dataset_dir = 'F:\\kaggle\\train'

# The directory where we will
# store our smaller dataset
base_dir = 'F:\\kaggle\\cats_and_dogs_small'
os.mkdir(base_dir)

# Directories for our training,
# validation and test splits
train_dir = os.path.join(base_dir, 'train')
os.mkdir(train_dir)
validation_dir = os.path.join(base_dir, 'validation')
os.mkdir(validation_dir)
test_dir = os.path.join(base_dir, 'test')
os.mkdir(test_dir)

# Directory with our training cat pictures
train_cats_dir = os.path.join(train_dir, 'cats')
os.mkdir(train_cats_dir)

# Directory with our training dog pictures
train_dogs_dir = os.path.join(train_dir, 'dogs')
os.mkdir(train_dogs_dir)

# Directory with our validation cat pictures
validation_cats_dir = os.path.join(validation_dir, 'cats')
os.mkdir(validation_cats_dir)

# Directory with our validation dog pictures
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
os.mkdir(validation_dogs_dir)

# Directory with our validation cat pictures
test_cats_dir = os.path.join(test_dir, 'cats')
os.mkdir(test_cats_dir)

# Directory with our validation dog pictures
test_dogs_dir = os.path.join(test_dir, 'dogs')
os.mkdir(test_dogs_dir)

# Copy first 1000 cat images to train_cats_dir
fnames = ['cat.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(train_cats_dir, fname)
    shutil.copyfile(src, dst)

# Copy next 500 cat images to validation_cats_dir
fnames = ['cat.{}.jpg'.format(i) for i in range(1000, 1500)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(validation_cats_dir, fname)
    shutil.copyfile(src, dst)
    
# Copy next 500 cat images to test_cats_dir
fnames = ['cat.{}.jpg'.format(i) for i in range(1500, 2000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(test_cats_dir, fname)
    shutil.copyfile(src, dst)
    
# Copy first 1000 dog images to train_dogs_dir
fnames = ['dog.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(train_dogs_dir, fname)
    shutil.copyfile(src, dst)
    
# Copy next 500 dog images to validation_dogs_dir
fnames = ['dog.{}.jpg'.format(i) for i in range(1000, 1500)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(validation_dogs_dir, fname)
    shutil.copyfile(src, dst)
    
# Copy next 500 dog images to test_dogs_dir
fnames = ['dog.{}.jpg'.format(i) for i in range(1500, 2000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(test_dogs_dir, fname)
    shutil.copyfile(src, dst)

運行結果:可以看到,分類之後,貓和狗的圖片被分別保存在了不同的文件夾下面。
在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述

驗證結果,分別查看輸出文件夾的圖片數:

print('total training cat images:', len(os.listdir(train_cats_dir)))
print('total training dog images:', len(os.listdir(train_dogs_dir)))
print('total validation cat images:', len(os.listdir(validation_cats_dir)))
print('total validation dog images:', len(os.listdir(validation_dogs_dir)))
print('total test cat images:', len(os.listdir(test_cats_dir)))
print('total test dog images:', len(os.listdir(test_dogs_dir)))

在這裏插入圖片描述

二、卷積神經網絡

1、搭建模型

from keras import layers
from keras import models

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu',
                        input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.summary()

在這裏插入圖片描述

2、讀取文件中數據,進行數據預處理

from keras import optimizers

model.compile(loss='binary_crossentropy',
              optimizer=optimizers.RMSprop(lr=1e-4),
              metrics=['acc'])
from keras.preprocessing.image import ImageDataGenerator

# All images will be rescaled by 1./255
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        # This is the target directory
        train_dir,
        # All images will be resized to 150x150
        target_size=(150, 150),
        batch_size=20,
        # Since we use binary_crossentropy loss, we need binary labels
        class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=20,
        class_mode='binary')

在這裏插入圖片描述
生成150x150rgb圖像(shape(20,150,150,3))和二進制標籤(shape(20,))。20是每批樣品的數量(批量大小)

for data_batch, labels_batch in train_generator:
    print('data batch shape:', data_batch.shape)
    print('labels batch shape:', labels_batch.shape)
    break

在這裏插入圖片描述

三、開始訓練

history = model.fit_generator(
      train_generator,
      steps_per_epoch=100,
      epochs=30,
      validation_data=validation_generator,
      validation_steps=50)

在這裏插入圖片描述
保存訓練模型:

model.save('F:\\kaggle\\cats_and_dogs_small_1.h5')

在這裏插入圖片描述
繪製模型的損失和準確性:

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))

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()

plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()

plt.show()

在這裏插入圖片描述這些曲線圖具有過度擬合的特點。隨着時間的推移,訓練準確率呈線性增長,直到接近100%,而我們的驗證準確率則停滯在70-72%。我們的驗證損失在五個階段後達到最小,然後停止,而訓練損失保持線性下降,直到接近0。

四、數據增強

datagen = ImageDataGenerator(
      rotation_range=40,
      width_shift_range=0.2,
      height_shift_range=0.2,
      shear_range=0.2,
      zoom_range=0.2,
      horizontal_flip=True,
      fill_mode='nearest')
# This is module with image preprocessing utilities
from keras.preprocessing import image

fnames = [os.path.join(train_cats_dir, fname) for fname in os.listdir(train_cats_dir)]

# We pick one image to "augment"
img_path = fnames[3]

# Read the image and resize it
img = image.load_img(img_path, target_size=(150, 150))

# Convert it to a Numpy array with shape (150, 150, 3)
x = image.img_to_array(img)

# Reshape it to (1, 150, 150, 3)
x = x.reshape((1,) + x.shape)

# The .flow() command below generates batches of randomly transformed images.
# It will loop indefinitely, so we need to `break` the loop at some point!
i = 0
for batch in datagen.flow(x, batch_size=1):
    plt.figure(i)
    imgplot = plt.imshow(image.array_to_img(batch[0]))
    i += 1
    if i % 4 == 0:
        break

plt.show()

在這裏插入圖片描述

五、過擬合、數據增強

1、過擬合

概念

過擬合是指爲了得到一致假設而使假設變得過度嚴格。避免過擬合是分類器設計中的一個核心任務。通常採用增大數據量和測試樣本集的方法對分類器性能進行評價。

定義

給定一個假設空間H,一個假設h屬於H,如果存在其他的假設h’屬於H,使得在訓練樣例上h的錯誤率比h’小,但在整個實例分佈上h’比h的錯誤率小,那麼就說假設h過度擬合訓練數據。

判斷方法

一個假設在訓練數據上能夠獲得比其他假設更好的擬合, 但是在訓練數據外的數據集上卻不能很好地擬合數據,此時認爲這個假設出現了過擬合的現象。出現這種現象的主要原因是訓練數據中存在噪音或者訓練數據太少。

常見原因

(1)建模樣本選取有誤,如樣本數量太少,選樣方法錯誤,樣本標籤錯誤等,導致選取的樣本數據不足以代表預定的分類規則;
(2)樣本噪音干擾過大,使得機器將部分噪音認爲是特徵從而擾亂了預設的分類規則;
(3)假設的模型無法合理存在,或者說是假設成立的條件實際並不成立;
(4)參數太多,模型複雜度過高;
(5)對於決策樹模型,如果我們對於其生長沒有合理的限制,其自由生長有可能使節點只包含單純的事件數據(event)或非事件數據(no event),使其雖然可以完美匹配(擬合)訓練數據,但是無法適應其他數據集。
(6)對於神經網絡模型:a)對樣本數據可能存在分類決策面不唯一,隨着學習的進行,,BP算法使權值可能收斂過於複雜的決策面;b)權值學習迭代次數足夠多(Overtraining),擬合了訓練數據中的噪聲和訓練樣例中沒有代表性的特徵。

解決方法

(1)在神經網絡模型中,可使用權值衰減的方法,即每次迭代過程中以某個小因子降低每個權值。
(2)選取合適的停止訓練標準,使對機器的訓練在合適的程度;
(3)保留驗證數據集,對訓練成果進行驗證;
(4)獲取額外數據進行交叉驗證;
(5)正則化,即在進行目標函數或代價函數優化時,在目標函數或代價函數後面加上一個正則項,一般有L1正則與L2正則等。

2、數據增強

數據集增強主要是爲了減少網絡的過擬合現象,通過對訓練圖片進行變換可以得到泛化能力更強的網絡,更好的適應應用場景。

常用的數據增強方法有:

1、旋轉 | 反射變換(Rotation/reflection): 隨機旋轉圖像一定角度; 改變圖像內容的朝向;
2、翻轉變換(flip): 沿着水平或者垂直方向翻轉圖像;
3、縮放變換(zoom): 按照一定的比例放大或者縮小圖像;
4、平移變換(shift): 在圖像平面上對圖像以一定方式進行平移;
5、可以採用隨機或人爲定義的方式指定平移範圍和平移步長, 沿水平或豎直方向進行平移. 改變圖像內容的位置;
6、尺度變換(scale): 對圖像按照指定的尺度因子, 進行放大或縮小; 或者參照SIFT特徵提取思想, 利用指定的尺度因子對圖像濾波構造尺度空間. 改變圖像內容的大小或模糊程度;
7、對比度變換(contrast): 在圖像的HSV顏色空間,改變飽和度S和V亮度分量,保持色調H不變. 對每個像素的S和V分量進行指數運算(指數因子在0.25到4之間), 增加光照變化;
8、噪聲擾動(noise): 對圖像的每個像素RGB進行隨機擾動, 常用的噪聲模式是椒鹽噪聲和高斯噪聲;
9、顏色變化:在圖像通道上添加隨機擾動。
10、輸入圖像隨機選擇一塊區域塗黑,參考《Random Erasing Data Augmentation》。
深入瞭解數據增強請點擊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章