一、狗貓數據集的兩階段分類實驗
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》。
深入瞭解數據增強請點擊