https://blog.csdn.net/weiwei9363/article/details/78635674
Image Data Augmentation In Keras
討論的內(nèi)容包括
Data Augmentation
ImageDataGenerator 的使用方法
在cifar-10數(shù)據(jù)集上使用Data Augmentation
完整代碼在 這里 下載
Data Augmentation
Data Aumentation(數(shù)據(jù)擴充)指的是在使用以下或者其他方法增加數(shù)據(jù)輸入量。這里,我們特指圖像數(shù)據(jù)柱恤。
旋轉(zhuǎn) | 反射變換(Rotation/reflection): 隨機旋轉(zhuǎn)圖像一定角度; 改變圖像內(nèi)容的朝向;
翻轉(zhuǎn)變換(flip): 沿著水平或者垂直方向翻轉(zhuǎn)圖像;
縮放變換(zoom): 按照一定的比例放大或者縮小圖像;
平移變換(shift): 在圖像平面上對圖像以一定方式進行平移;
可以采用隨機或人為定義的方式指定平移范圍和平移步長, 沿水平或豎直方向進行平移. 改變圖像內(nèi)容的位置;
尺度變換(scale): 對圖像按照指定的尺度因子, 進行放大或縮小; 或者參照SIFT特征提取思想, 利用指定的尺度因子對圖像濾波構(gòu)造尺度空間. 改變圖像內(nèi)容的大小或模糊程度;
對比度變換(contrast): 在圖像的HSV顏色空間歼跟,改變飽和度S和V亮度分量灭红,保持色調(diào)H不變. 對每個像素的S和V分量進行指數(shù)運算(指數(shù)因子在0.25到4之間), 增加光照變化;
噪聲擾動(noise): 對圖像的每個像素RGB進行隨機擾動, 常用的噪聲模式是椒鹽噪聲和高斯噪聲;
Data Aumentation 有很多好處悉罕,比如數(shù)據(jù)量太小了台盯,我們用數(shù)據(jù)擴充來增加訓練數(shù)據(jù),或者通過Data Aumentation防止過擬合的問題痴施。
在Keras中,ImageDataGenerator就是干這個事情的,特別方便辣吃。接下來动遭,我們就聊聊ImageDataGenerator的使用方法
from keras.preprocessing.image import ImageDataGenerator
from keras.preprocessing import image
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
Using TensorFlow backend.
ImageDataGenerator for Single image
ImageDataGenerator 參數(shù)很多,詳見這里或者在python環(huán)境下輸入ImageDataGenerator?神得,我們先看一個例子厘惦,這個例子將對一張圖片進行數(shù)據(jù)擴充
# 指定參數(shù)
# rotation_range 旋轉(zhuǎn)
# width_shift_range 左右平移
# height_shift_range 上下平移
# zoom_range 隨機放大或縮小
img_generator = ImageDataGenerator(
? ? rotation_range = 90,
? ? width_shift_range = 0.2,
? ? height_shift_range = 0.2,
? ? zoom_range = 0.3
? ? )
# 導入并顯示圖片
img_path = './imgs/dog.jpg'
img = image.load_img(img_path)
plt.imshow(img)
<matplotlib.image.AxesImage at 0x7fd738246d30>
flow()將會返回一個生成器,這個生成器用來擴充數(shù)據(jù)哩簿,每次都會產(chǎn)生batch_size個樣本宵蕉。
因為目前我們只導入了一張圖片,因此每次生成的圖片都是基于這張圖片而產(chǎn)生的节榜,可以看到結(jié)果羡玛,旋轉(zhuǎn)、位移全跨、放大縮小缝左,統(tǒng)統(tǒng)都有。
flow()可以將產(chǎn)生的圖片進行保存浓若,詳見 深度學習中的Data Augmentation方法和代碼實現(xiàn)
生成圖片的過程大概是這樣的渺杉,并且可以一直一直一直無限循環(huán)的生成
# 將圖片轉(zhuǎn)為數(shù)組
x = image.img_to_array(img)
# 擴充一個維度
x = np.expand_dims(x, axis=0)
# 生成圖片
gen = img_generator.flow(x, batch_size=1)
# 顯示生成的圖片
plt.figure()
for i in range(3):
? ? for j in range(3):
? ? ? ? x_batch = next(gen)
? ? ? ? idx = (3*i) + j
? ? ? ? plt.subplot(3, 3, idx+1)
? ? ? ? plt.imshow(x_batch[0]/256)
x_batch.shape
(1, 160, 240, 3)
ImageDataGenerator for Multiple image
單張圖片的數(shù)據(jù)擴展我們已經(jīng)演示完畢了,但是通常情況下挪钓,我們應該是有一個不太大的訓練集需要Data Aumentation或者為了防止過擬合是越,總之,就是對一組數(shù)據(jù)進行Data Aumentation碌上。這里我們以cifar-10數(shù)據(jù)庫做一個演示倚评。
我們將進行一組實驗,比較訓練之后的測試結(jié)果:
cifar-10 20%數(shù)據(jù)
cifar-10 20%數(shù)據(jù) + Data Augmentation
from keras.datasets import cifar10
from keras.layers.core import Dense, Flatten, Activation, Dropout
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.models import Sequential
from keras.utils import np_utils
(x_train, y_train),(x_test, y_test) = cifar10.load_data()
print(x_train.shape, y_train.shape, x_test.shape, y_test.shape)
(50000, 32, 32, 3) (50000, 1) (10000, 32, 32, 3) (10000, 1)
def preprocess_data(x):
? ? x /= 255
? ? x -= 0.5
? ? x *= 2
? ? return x
# 預處理
x_train = x_train.astype(np.float32)
x_test = x_test.astype(np.float32)
x_train = preprocess_data(x_train)
x_test = preprocess_data(x_test)
# one-hot encoding
n_classes = 10
y_train = np_utils.to_categorical(y_train, n_classes)
y_test = np_utils.to_categorical(y_test, n_classes)
# 取 20% 的訓練數(shù)據(jù)
x_train_part = x_train[:10000]
y_train_part = y_train[:10000]
print(x_train_part.shape, y_train_part.shape)
(10000, 32, 32, 3) (10000, 10)
# 建立一個簡單的卷積神經(jīng)網(wǎng)絡
def build_model():
? ? model = Sequential()
? ? model.add(Conv2D(64, (3,3), input_shape=(32,32,3)))
? ? model.add(Activation('relu'))
? ? model.add(BatchNormalization(scale=False, center=False))
? ? model.add(Conv2D(32, (3,3)))
? ? model.add(Activation('relu'))
? ? model.add(MaxPooling2D((2,2)))
? ? model.add(Dropout(0.2))
? ? model.add(BatchNormalization(scale=False, center=False))
? ? model.add(Flatten())
? ? model.add(Dense(256))
? ? model.add(Activation('relu'))
? ? model.add(Dropout(0.2))
? ? model.add(BatchNormalization())
? ? model.add(Dense(n_classes))
? ? model.add(Activation('softmax'))
? ? return model
# 訓練參數(shù)
batch_size = 128
epochs = 20
cifar-10 20%數(shù)據(jù)
model = build_model()
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train_part, y_train_part, epochs=epochs, batch_size=batch_size, verbose=1, validation_split=0.1)
Train on 9000 samples, validate on 1000 samples
Epoch 1/20
9000/9000 [==============================] - 8s 844us/step - loss: 1.8075 - acc: 0.4040 - val_loss: 2.9955 - val_acc: 0.1150
Epoch 2/20
9000/9000 [==============================] - 3s 343us/step - loss: 1.2029 - acc: 0.5742 - val_loss: 3.0341 - val_acc: 0.1910
Epoch 3/20
9000/9000 [==============================] - 3s 342us/step - loss: 0.9389 - acc: 0.6690 - val_loss: 2.8508 - val_acc: 0.1580
...........
...........
Epoch 18/20
9000/9000 [==============================] - 5s 597us/step - loss: 0.0668 - acc: 0.9824 - val_loss: 1.6110 - val_acc: 0.5840
Epoch 19/20
9000/9000 [==============================] - 6s 629us/step - loss: 0.0681 - acc: 0.9826 - val_loss: 1.5807 - val_acc: 0.5980
Epoch 20/20
9000/9000 [==============================] - 5s 607us/step - loss: 0.0597 - acc: 0.9847 - val_loss: 1.6222 - val_acc: 0.5930
loss, acc = model.evaluate(x_test, y_test, batch_size=32)
print('Loss: ', loss)
print('Accuracy: ', acc)
10000/10000 [==============================] - 4s 444us/step
Loss:? 1.65560287151
Accuracy:? 0.6058
經(jīng)過20輪的訓練之后馏予,在訓練集上已經(jīng)有98%以上的準確率天梧,但是在測試集上只有60%左右的準確率,可以說是過擬合了霞丧,主要原因就是訓練集太小了呢岗,無法達到很好的效果。那么接下來我們試試經(jīng)過Data Augmentation之后的準確率如何
cifar-10 20%數(shù)據(jù) + Data Augmentation
在進行Data Augmentation時要注意的就是:生成的數(shù)據(jù)是有意義的蛹尝。比如說對于某些醫(yī)療圖像后豫,如果進行了旋轉(zhuǎn),那么這個數(shù)據(jù)就屬于采樣錯誤突那,是沒用的了挫酿。因此,在設置生成參數(shù)時要結(jié)合實際的情況愕难。
# 設置生成參數(shù)
img_generator = ImageDataGenerator(
? ? rotation_range = 20,
? ? width_shift_range = 0.2,
? ? height_shift_range = 0.2,
? ? zoom_range = 0.2
? ? )
下面的代碼是一種“手動”的訓練方式早龟,Progbar是進度條惫霸,用于顯示訓練進度。
另外一種“自動”的方法拄衰,請參考 官網(wǎng)給的例子 中 model.fit_generator的用法
from keras.utils import generic_utils
model_2 = build_model()
model_2.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# Data Augmentation后它褪,數(shù)據(jù)變多了,因此我們需要更的訓練次數(shù)
for e in range(epochs*4):
? ? print('Epoch', e)
? ? print('Training...')
? ? progbar = generic_utils.Progbar(x_train_part.shape[0])
? ? batches = 0
? ? for x_batch, y_batch in img_generator.flow(x_train_part, y_train_part, batch_size=batch_size, shuffle=True):
? ? ? ? loss,train_acc = model_2.train_on_batch(x_batch, y_batch)
? ? ? ? batches += x_batch.shape[0]
? ? ? ? if batches > x_train_part.shape[0]:
? ? ? ? ? ? break
? ? ? ? progbar.add(x_batch.shape[0], values=[('train loss', loss),('train acc', train_acc)])
Epoch 0
Training...
10000/10000 [==============================] - 13s 1ms/step - train loss: 2.0455 - train acc: 0.3187
Epoch 1
Training...
10000/10000 [==============================] - 10s 1ms/step - train loss: 1.7304 - train acc: 0.3857
Epoch 2
Training...
10000/10000 [==============================] - 10s 1ms/step - train loss: 1.6195 - train acc: 0.4220
Epoch 3
Training...
10000/10000 [==============================] - 10s 1ms/step - train loss: 1.5595 - train acc: 0.4417
.........
.........
Epoch 76
Training...
10000/10000 [==============================] - 9s 874us/step - train loss: 0.8809 - train acc: 0.6890
Epoch 77
Training...
10000/10000 [==============================] - 9s 891us/step - train loss: 0.8776 - train acc: 0.6949
Epoch 78
Training...
10000/10000 [==============================] - 9s 892us/step - train loss: 0.8723 - train acc: 0.6916
Epoch 79
Training...
10000/10000 [==============================] - 9s 892us/step - train loss: 0.8737 - train acc: 0.6919
loss, acc = model_2.evaluate(x_test, y_test, batch_size=32)
print('Loss: ', loss)
print('Accuracy: ', acc)
10000/10000 [==============================] - 5s 455us/step
Loss:? 0.842164948082
Accuracy:? 0.7057
哇塞翘悉!經(jīng)過Data Augmentation之后茫打,測試的準去率已經(jīng)有70%,提高了10%妖混。并且我相信繼續(xù)增加訓練次數(shù)準確率將會繼續(xù)上升老赤。
好的,實驗到此結(jié)束制市,這里只是給出一個簡單的Data Augmentation實現(xiàn)方法抬旺,ImageDataGenerator這個類,還有其他有趣的功能我們還沒有用到祥楣,有興趣的同學可以在 這里 進行詳細的閱讀开财。網(wǎng)絡上也有很多關于Data Augenmentation的討論,希望可以幫助到大家误褪。
使用深度學習(CNN)算法進行圖像識別工作時责鳍,有哪些data augmentation 的奇技淫巧?
The Effectiveness of Data Augmentation in Image Classification using Deep
Learning
keras面向小數(shù)據(jù)集的圖像分類(VGG-16基礎上fine-tune)實現(xiàn)(附代碼)