使用Keras進行深度學習的圖像增強(Image Augmentation)

使用Keras進行深度學習的圖像增強(Image Augmentation)

來自專欄深度學習+自然語言處理(NLP)17 人贊了文章

改編自文章《Image Augmentation for Deep Learning With Keras》,原文地址:

Image Augmentation for Deep Learning With Keras

本文使用的圖片來自kaggle競賽「Humpback Whale Identification Challenge」,競賽地址:Humpback Whale Identification Challenge

對原文做了如下改動:

  1. 改用kaggle競賽數據集
  2. 修改一些說法
  3. 增加了「其他增強方式」部分內容
  4. 對代碼進行了簡化

Keras 圖片增強 API

就像Keras的其他api一樣,圖像增強API簡單且強大。

Keras提供了ImageDataGenerator類,定義關於圖片準備和增強的配置。包括以下功能:

  • 樣本級的標準化
  • 特徵級的標準化
  • ZCA白化.
  • 隨機旋轉、轉換、剪切、翻轉
  • 維度重排.
  • 將增強的圖片保存在本地.

你可以通過以下方式創建ImageDataGenerator()的實例:

from keras.preprocessing.image import ImageDataGenerator # inport apidatagen = ImageDataGenerator()

相較於在內存中對數據集應用所有的操作,keras API被設計成在深度學習模型訓練過程中以實時可迭代的方式創建增強圖片。這種設計能夠減少內存的負擔,但是在模型訓練是會增加一些額外的時間消耗。

當你創建並設置好ImageDataGenerator()的實例,接下來需要將該實例應用到你的數據集上。

這個過程將計算所有需要使用的數據用於轉換你的圖片。你可以通過使用fit()方法來實現,該函數使用剛剛生成的ImageDataGenerator()實例和你的訓練數據。

datagen.fit(train)

實際上ImageDataGenerator()的實例是一個迭代器, 能夠按批次返回增強的圖片。我們可以使用實例的flow()方法來實現,該方法的需要的參數有批次大小batch size和數據集。

X_batch, y_batch = datagen.flow(train, train, batch_size=32)

當我們想在模型中使用生成的圖片時,必須使用fit_generator()方法代替fit()方法,指定使用的「圖片生成器實例」、「每次迭代使用的樣本數」和「迭代次數」。

model.fit_generator(datagen, samples_per_epoch=len(train), epochs=100)

數據集

接下來我們使用實際數據集用來舉例,數據集來自kaggle競賽Humpback Whale Identification Challenge

我們首先讀入並展示數據集:

from glob import globimport numpy as npfrom PIL import Imageimport pandas as pdtrain_images = glob("../input/train/*jpg") #return all jpg images pathtest_images = glob("../input/test/*jpg") df = pd.read_csv("../input/train.csv") #read in label filedf["Image"] = df["Image"].map(lambda x : "../input/train/"+x) #replace image name to file pathImageToLabelDict = dict(zip(df["Image"], df["Id"])) #convert to dict typedef ImportImage(filename, SIZE): img = Image.open(filename).convert("LA").resize( (SIZE,SIZE)) # open, convert to gray and resize image return np.array(img)[:,:,0]SIZE = 64train_img = np.array([ImportImage(img, SIZE) for img in train_images]) # reading image and save to arrayx = train_imgimport matplotlib.pylab as pltfrom matplotlib import pyplotdef plotImages( images_arr, n_images=3): fig, axes = plt.subplots(n_images, n_images, figsize=(10,10)) axes = axes.flatten() for img, ax in zip( images_arr, axes): if img.ndim != 2: img = img.reshape((SIZE,SIZE)) ax.imshow(img, cmap=pyplot.get_cmap(gray)) ax.set_xticks(()) ax.set_yticks(()) plt.tight_layout()plotImages(x)

數據集中的數據是鯨魚的尾巴圖片。下面我們對這些圖片進行圖像增強處理。

特徵標準化

我們也可以對整個圖像的像素值進行標準化。這也稱作特徵值標準化(feature standardization),類似於對表格化的數據集的每一列執行標準化操作。

你可以通過設置featurewise_centerfeaturewise_std_normalization應用特徵標準化,實際上,這兩個參數的默認預設值就是True

from sklearn.preprocessing import StandardScaler, OneHotEncoder, LabelEncoderclass LabelOneHotEncoder(): def __init__(self): self.ohe = OneHotEncoder() self.le = LabelEncoder() def fit_transform(self, x): features = self.le.fit_transform( x) return self.ohe.fit_transform( features.reshape(-1,1)) def transform( self, x): return self.ohe.transform( self.le.transform( x.reshape(-1,1))) def inverse_tranform( self, x): return self.le.inverse_transform( self.ohe.inverse_tranform( x)) def inverse_labels( self, x): return self.le.inverse_transform( x)from keras.preprocessing.image import ImageDataGenerator# one-hot encoding the labelsImageToLabelDict = dict(zip(df["Image"], df["Id"])) #convert to dict typey = list(map(ImageToLabelDict.get, train_images))lohe = LabelOneHotEncoder()y_cat = lohe.fit_transform(y)y_train = y_cat# reshape and transform to floatx = x.reshape((-1,SIZE,SIZE,1))x_train = x.astype("float32")# create image gtenerator instancedatagen = ImageDataGenerator(featurewise_center=True, featurewise_std_normalization=True)# fit parameters from datadatagen.fit(x_train,augment=True)# configure batch size and retrieve one batch of imagesfor x_batch, y_batch in datagen.flow(x_train, y_train.toarray(), batch_size=9, shuffle = False): # create a grid of 4x4 images fig, axes = plt.subplots(3, 3, figsize=(10,10)) axes = axes.flatten() for i in range(0, 9): print(標準化之前的均值是:%f之後是:%f%(x_train[i].mean(),x_batch[i].mean())) print(標準化之前的方差是:%f之後是:%f%(x_train[i].std(),x_batch[i].std())) axes[i].imshow(x_batch[i].reshape(SIZE, SIZE), cmap=pyplot.get_cmap(gray)) axes[i].set_xticks(()) axes[i].set_yticks(()) plt.tight_layout() break

標準化之前的均值是:124.352051之後是:-0.318896標準化之前的方差是:57.989574之後是:0.840124標準化之前的均值是:106.168457之後是:-0.582330標準化之前的方差是:39.908623之後是:0.578176標準化之前的均值是:134.744385之後是:-0.168337標準化之前的方差是:52.553974之後是:0.761376標準化之前的均值是:80.210205之後是:-0.958401標準化之前的方差是:48.334305之後是:0.700243標準化之前的均值是:163.198730之後是:0.243896標準化之前的方差是:58.688942之後是:0.850256標準化之前的均值是:175.447754之後是:0.421353標準化之前的方差是:63.631710之後是:0.921864標準化之前的均值是:164.416992之後是:0.261545標準化之前的方差是:79.251526之後是:1.148156標準化之前的均值是:133.880371之後是:-0.180854標準化之前的方差是:22.195881之後是:0.321563標準化之前的均值是:144.296143之後是:-0.029956標準化之前的方差是:71.543716之後是:1.036489

可見經過標準化,圖片的均值近似為0,方差近似為1.由於我們的圖片是灰度圖,因此直觀上沒有影響。

ZCA白化

圖片的白化轉換是通過一種線性代數的操作,減少圖片的冗餘。讀者可以看這篇文章

更少的冗餘意味著更加凸顯圖像的結構和特徵,減少雜訊。

一般來說,圖像白化通過使用主成分分析,即PCA,來實現。一種效果更好用稱為ZCA,這裡使用的就是ZCA。

你可以通過設置zca_whitening參數為True來實現zca白化.

def show_augment_image(x_train, y_train,datagen): # configure batch size and retrieve one batch of images for x_batch, y_batch in datagen.flow(x_train, y_train.toarray(), batch_size=9, shuffle = False): # create a grid of 4x4 images fig, axes = plt.subplots(3, 3, figsize=(10,10)) axes = axes.flatten() for i in range(0, 9): axes[i].imshow(x_batch[i].reshape(SIZE, SIZE), cmap=pyplot.get_cmap(gray)) axes[i].set_xticks(()) axes[i].set_yticks(()) plt.tight_layout() breakdatagen = ImageDataGenerator(zca_whitening=True)datagen.fit(x_train)show_augment_image(x_train, y_train,datagen)

觀察上圖,鯨魚尾巴的輪廓和特徵信息被保留並增強,而其他信息被弱化。

隨機旋轉

你數據集的圖片可能有不同程度的翻旋轉。

你可以通過隨機旋轉你的訓練集圖片來得到對旋轉的圖像性能更好的模型。

你可以通過設置rotation_range argument來實現這一點,90的含義是最多旋轉90度。

datagen = ImageDataGenerator(rotation_range=90)datagen.fit(x_train)show_augment_image(x_train, y_train,datagen)

觀察上圖,圖片被隨機向左或向右旋轉了一定度數,最多不超過90度。

隨機轉換

你的目標物不一定在圖片的中心,而是很有可能偏向一側。

你可以通過隨機生成轉換了一定程度的訓練集圖片,使你的模型對於圖像的轉換有更好的魯棒性。

你可以通過keras的width_shift_rangeheight_shift_range arguments參數來使圖像在寬度或高度方向上轉換。0.2代表在這個方向上轉換的長/寬佔總長/寬的比例。

# define data preparationshift = 0.2datagen = ImageDataGenerator(width_shift_range=shift, height_shift_range=shift)datagen.fit(x_train)show_augment_image(x_train, y_train,datagen)

隨機翻轉

另一個圖片增強的操作就是隨機翻轉。

Keras支持沿著垂直或水平方向進行隨機翻轉。只需要設置vertical_fliphorizontal_flip參數.

datagen = ImageDataGenerator(horizontal_flip=True, vertical_flip=True)datagen.fit(X_train)show_augment_image(x_train, y_train,datagen)

我們發現,圖片被隨機翻轉了,但是這種翻轉並不完全適合我們的數據集,並不需要垂直翻轉。

保存增強圖片

keras實時應用數據準備和圖像增強。

這種方式在內存使用方面效率較高,但是,你可能需要這些增強的圖片用於訓練。例如,可能你想使用不同的圖片處理庫來處理這些圖片,或者你想一次生成這些圖片,然後在不同的深度學習模型中使用它們。

Keras允許你在訓練的過程中保存這些生成的圖片。在訓練你的模型之前,你可以事先設定flow()方法的directory, filename prefiximage file type參數,這樣,在訓練過程中,生成的圖片就會寫入文件中。

下面這個例子保存了9張圖片到「aug_images」子文件夾,文件的前綴是"aug",圖片類型是png。

import osdatagen = ImageDataGenerator()# fit parameters from datadatagen.fit(x_train)# configure batch size and retrieve one batch of imagestry: os.makedirs(aug_images)except: for X_batch, y_batch in datagen.flow(x_train, y_train.toarray(), batch_size=9, save_to_dir=aug_images, save_prefix=aug, save_format=png): # create a grid of 3x3 images for i in range(0, 9): pyplot.subplot(330 + 1 + i) pyplot.imshow(X_batch[i].reshape(SIZE, SIZE), cmap=pyplot.get_cmap(gray)) # show the plot pyplot.show() break

檢查aug_images子文件夾,在訓練過程中生成的圖片已經被保存。

其他增強方式

以下是ImageDataGenerator類可以設置的其他參數,這裡不一一演示,讀者可以自行探索,這裡僅列出並說明。

  • shear_range: 對圖像進行斜切,參數是延逆時針方向斜切的度數。
  • zoom_range:對圖像進行放大,參數設置是放大的百分比,[0-1],如果是0.5,就是放大一倍
  • channel_shift_range:通道轉換範圍,對RGB通道的數值進行轉換
  • fill_mode:填充方式,默認為「近鄰填充」,還有多種填充方式{"constant", "nearest", "reflect" or "wrap"},讀者可以探索.
  • cval:當fill_mode設置為"constant"時,設定填充的值。
  • rescale:重新縮放,在應用所有變換之前,先對所有像素乘以這個rescale數值,一般可以設置1.0/255
  • preprocessing_function:自定義函數,可以設置自定義函數,這個函數的輸入為一個Numpy tensor 格式的3維數組。
  • data_format:圖片格式,通道在前還是通道在後,如果是"channels_first"就是輸入圖片的第一個維度代表通道,如果是"channels_last"代表輸入圖片的第三個維度代表通道。
  • validation_split:驗證比例,設置一個0到1的比例,該比例的圖片作為驗證集數據。

使用keras做圖片增強的技巧

圖像數據的獨特性在於,你可以檢查數據並且轉換數據,並快速的在模型中得到驗證,理解圖像轉換的效果。

以下是一些處理技巧:

  • 檢查數據集。花一些時間詳細的檢查你的數據集。查看圖片,記錄可以使你的模型訓練收益的圖片增強方式,例如你需要應用不同的轉換、翻轉、旋轉等。
  • 檢查增強後的圖片。在對圖像進行增強後檢查樣本圖像。知道你在使用什麼樣的增強圖像是一回事,檢查樣例是另一回事。檢查你正在使用的單個增強圖像,以及你計劃使用的全部。您可能會想到簡化或進一步加強模型訓練過程的方法。
  • 評估多種圖像轉換技術。嘗試使用不止一種圖像準備和增強模式。你會被一些你以為沒啥用的數據準備模型驚艷到。

總結

這篇文章探討了keras的keras.preprocessing.image.ImageDataGenerator類。

你學習了一些列的簡單易用的圖像處理方法。

  • Keras的ImageDataGenerator API,用於實時轉換圖像。
  • 樣本級的以及特徵級的像素標準化。
  • ZCA白化轉換
  • 隨機翻轉、轉換、旋轉圖像.
  • 如何保存圖像到本地

感謝閱讀,歡迎留言討論!


推薦閱讀:

簡單邏輯回歸擬合數據代碼
教你用PyTorch實現「看圖說話」(附代碼、學習資源)
深度學習任務面臨非平衡數據問題?試試這個簡單方法
淺入淺出TensorFlow 8 - 行人分割
深度學習 用於 音樂生成的書籍推薦?

TAG:Keras | 深度學習DeepLearning | TensorFlow |