天天看點

深度學習基礎系列(十一)| Keras中圖像增強技術詳解

  在深度學習中,資料短缺是我們經常面臨的一個問題,雖然現在有不少公開資料集,但跟大公司掌握的海量資料集相比,數量上仍然偏少,而某些特定領域的資料采集更是非常困難。根據之前的學習可知,資料量少帶來的最直接影響就是過拟合。那有沒有辦法在現有少量資料基礎上,降低或解決過拟合問題呢?

      答案是有的,就是資料增強技術。我們可以對現有的資料,如圖檔資料進行平移、翻轉、旋轉、縮放、亮度增強等操作,以生成新的圖檔來參與訓練或測試。這種操作可以将圖檔數量提升數倍,由此大大降低了過拟合的可能。本文将詳解圖像增強技術在Keras中的原理和應用。

一、Keras中的ImageDataGenerator類

  圖像增強的官網位址是:https://keras.io/preprocessing/image/ ,API使用相對簡單,功能也很強大。

  先介紹的是ImageDataGenerator類,這個類定義了圖檔該如何進行增強操作,其API及參數定義如下:

keras.preprocessing.image.ImageDataGenerator(
    featurewise_center=False, #輸入值按照均值為0進行處理
    samplewise_center=False, #每個樣本的均值按0處理
    featurewise_std_normalization=False, #輸入值按照标準正态化處理
    samplewise_std_normalization=False, #每個樣本按照标準正态化處理 
    zca_whitening=False, # 是否開啟增白
    zca_epsilon=1e-06, 
    rotation_range=0, #圖像随機旋轉一定角度,最大旋轉角度為設定值
    width_shift_range=0.0, #圖像随機水準平移,最大平移值為設定值。若值為小于1的float值,則可認為是按比例平移,若大于1,則平移的是像素;若值為整型,平移的也是像素;假設像素為2.0,則移動範圍為[-1,1]之間
    height_shift_range=0.0, #圖像随機垂直平移,同上
    brightness_range=None, # 圖像随機亮度增強,給定一個含兩個float值的list,亮度值取自上下限值間
    shear_range=0.0, # 圖像随機修剪
    zoom_range=0.0, # 圖像随機變焦 
    channel_shift_range=0.0, 
    fill_mode=\'nearest\', #填充模式,預設為最近原則,比如一張圖檔向右平移,那麼最左側部分會被臨近的圖案覆寫
    cval=0.0, 
    horizontal_flip=False, #圖像随機水準翻轉
    vertical_flip=False, #圖像随機垂直翻轉
    rescale=None, #縮放尺寸
    preprocessing_function=None, 
    data_format=None, 
    validation_split=0.0, 
    dtype=None)      

   下文将以mnist和花類的資料集進行圖檔操作,其中花類(17種花,共1360張圖檔)資料集可見我的百度網盤: https://pan.baidu.com/s/1YDA_VOBlJSQEijcCoGC60w 。讓我們以直覺地方式看看各參數能帶來什麼樣的圖檔變化。

   随機旋轉

  我們可用mnist資料集對圖檔進行随機旋轉,旋轉的最大角度由參數定義。

from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
from keras import backend as K

K.set_image_dim_ordering(\'th\')

(train_data, train_label), (test_data, test_label) = mnist.load_data()
train_data = train_data.reshape(train_data.shape[0], 1, 28, 28)
train_data = train_data.astype(\'float32\')

# 建立圖像生成器,指定對圖像操作的内容
datagen = ImageDataGenerator(rotation_range=90)
# 圖像生成器要訓練的資料
datagen.fit(train_data)

# 這是個圖像生成疊代器,是可以無限生成各種新圖檔,我們指定每輪疊代隻生成9張圖檔
for batch_data, batch_label in datagen.flow(train_data, train_label, batch_size=9):
    for i in range(0, 9):
        # 建立一個 3*3的九宮格,以顯示圖檔
        pyplot.subplot(330 + 1 + i)
        pyplot.imshow(batch_data[i].reshape(28, 28), cmap=pyplot.get_cmap(\'gray\'))
    pyplot.show()
    break      

  生成結果為:

深度學習基礎系列(十一)| Keras中圖像增強技術詳解

  随機平移

  我們可用花類資料集對圖檔進行随機平移,可以在垂直和水準方向上平移,平移最大值由參數定義。

from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
from keras.preprocessing.image import array_to_img

IMAGE_SIZE = 224
NUM_CLASSES = 17
TRAIN_PATH = \'/home/yourname/Documents/tensorflow/images/17flowerclasses/train\'
TEST_PATH = \'/home/yourname/Documents/tensorflow/images/17flowerclasses/test\'
FLOWER_CLASSES = [\'Bluebell\', \'ButterCup\', \'ColtsFoot\', \'Cowslip\', \'Crocus\', \'Daffodil\', \'Daisy\',
                  \'Dandelion\', \'Fritillary\', \'Iris\', \'LilyValley\', \'Pansy\', \'Snowdrop\', \'Sunflower\',
                  \'Tigerlily\', \'tulip\', \'WindFlower\']

# 建立圖像生成器,指定對圖像操作的内容,平移的最大比例為50%
train_datagen = ImageDataGenerator(width_shift_range=0.5, height_shift_range=0.5)

# 這是個圖像生成疊代器,是可以無限生成各種新圖檔,我們指定每輪疊代隻生成9張圖檔
for X_batch, y_batch in train_datagen.flow_from_directory(directory=TRAIN_PATH, target_size=(IMAGE_SIZE, IMAGE_SIZE),batch_size=9, classes=FLOWER_CLASSES):
    for i in range(0, 9):
        pyplot.subplot(330 + 1 + i)
        pyplot.imshow(array_to_img(X_batch[i]))
    pyplot.show()
    break      

  生成結果為:

深度學習基礎系列(十一)| Keras中圖像增強技術詳解

  可以觀察到,圖檔除了實作平移外,其原來的位置都被最近的圖案給填充,因為預設給的填充方式是nearest。

  随機亮度調整

  我們可用花類資料集對圖檔進行随機亮度調整,亮度範圍由參數定義。

from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
from keras.preprocessing.image import array_to_img

IMAGE_SIZE = 224
NUM_CLASSES = 17
TRAIN_PATH = \'/home/yourname/Documents/tensorflow/images/17flowerclasses/train\'
TEST_PATH = \'/home/yourname/Documents/tensorflow/images/17flowerclasses/test\'
FLOWER_CLASSES = [\'Bluebell\', \'ButterCup\', \'ColtsFoot\', \'Cowslip\', \'Crocus\', \'Daffodil\', \'Daisy\',
                  \'Dandelion\', \'Fritillary\', \'Iris\', \'LilyValley\', \'Pansy\', \'Snowdrop\', \'Sunflower\',
                  \'Tigerlily\', \'tulip\', \'WindFlower\']

# 建立圖像生成器,指定對圖像操作的内容,亮度範圍在0.1~10之間随機選擇
train_datagen = ImageDataGenerator(brightness_range=[0.1, 10])

# 這是個圖像生成疊代器,是可以無限生成各種新圖檔,我們指定每輪疊代隻生成9張圖檔
for X_batch, y_batch in train_datagen.flow_from_directory(directory=TRAIN_PATH, target_size=(IMAGE_SIZE, IMAGE_SIZE),batch_size=9, classes=FLOWER_CLASSES):
    for i in range(0, 9):
        pyplot.subplot(330 + 1 + i)
        pyplot.imshow(array_to_img(X_batch[i]))
    pyplot.show()
    break      

  生成結果為:

深度學習基礎系列(十一)| Keras中圖像增強技術詳解

  随機焦距調整

  我們可用mnist資料集對圖檔進行随機焦距調整,焦距調整值由參數定義。

from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
from keras import backend as K

K.set_image_dim_ordering(\'th\')

(train_data, train_label), (test_data, test_label) = mnist.load_data()
train_data = train_data.reshape(train_data.shape[0], 1, 28, 28)
train_data = train_data.astype(\'float32\')

# 建立圖像生成器,指定對圖像操作的内容,焦距值在0.1~1之間
datagen = ImageDataGenerator(zoom_range=[0.1, 1])
# 圖像生成器要訓練的資料
datagen.fit(train_data)

# 這是個圖像生成疊代器,是可以無限生成各種新圖檔,我們指定每輪疊代隻生成9張圖檔
for batch_data, batch_label in datagen.flow(train_data, train_label, batch_size=9):
    for i in range(0, 9):
        # 建立一個 3*3的九宮格,以顯示圖檔
        pyplot.subplot(330 + 1 + i)
        pyplot.imshow(batch_data[i].reshape(28, 28), cmap=pyplot.get_cmap(\'gray\'))
    pyplot.show()
    break      

  生成結果為:

深度學習基礎系列(十一)| Keras中圖像增強技術詳解

  可以看出這跟相機調焦一樣,可以放大或縮小焦距。

  随機翻轉

  我們可用花類資料集對圖檔進行随機翻轉。

from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
from keras.preprocessing.image import array_to_img

IMAGE_SIZE = 224
NUM_CLASSES = 17
TRAIN_PATH = \'/home/hutao/Documents/tensorflow/images/17flowerclasses/train\'
TEST_PATH = \'/home/hutao/Documents/tensorflow/images/17flowerclasses/test\'
FLOWER_CLASSES = [\'Bluebell\', \'ButterCup\', \'ColtsFoot\', \'Cowslip\', \'Crocus\', \'Daffodil\', \'Daisy\',
                  \'Dandelion\', \'Fritillary\', \'Iris\', \'LilyValley\', \'Pansy\', \'Snowdrop\', \'Sunflower\',
                  \'Tigerlily\', \'tulip\', \'WindFlower\']

# 建立圖像生成器,指定對圖像操作的内容,圖檔随機翻轉
train_datagen = ImageDataGenerator(horizontal_flip=True, vertical_flip=True)

# 這是個圖像生成疊代器,是可以無限生成各種新圖檔,我們指定每輪疊代隻生成9張圖檔
for X_batch, y_batch in train_datagen.flow_from_directory(directory=TRAIN_PATH, target_size=(IMAGE_SIZE, IMAGE_SIZE),batch_size=9, classes=FLOWER_CLASSES):
    for i in range(0, 9):
        pyplot.subplot(330 + 1 + i)
        pyplot.imshow(array_to_img(X_batch[i]))
    pyplot.show()
    break      

  生成結果為:

深度學習基礎系列(十一)| Keras中圖像增強技術詳解

  從上圖可看出,有些圖檔水準翻轉了,有些是垂直翻轉了。

  ZCA圖像增白

  說實在我不太清楚該技術有何用,用花類圖檔實驗結果顯示zca不支援,可以用mnist資料集來看看效果。

from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
from keras import backend as K

K.set_image_dim_ordering(\'th\')

(train_data, train_label), (test_data, test_label) = mnist.load_data()
train_data = train_data.reshape(train_data.shape[0], 1, 28, 28)
train_data = train_data.astype(\'float32\')

# 建立圖像生成器,指定對圖像操作的内容,增白圖檔
datagen = ImageDataGenerator(zca_whitening=True)
# 圖像生成器要訓練的資料
datagen.fit(train_data)

# 這是個圖像生成疊代器,是可以無限生成各種新圖檔,我們指定每輪疊代隻生成9張圖檔
for batch_data, batch_label in datagen.flow(train_data, train_label, batch_size=9):
    for i in range(0, 9):
        # 建立一個 3*3的九宮格,以顯示圖檔
        pyplot.subplot(330 + 1 + i)
        pyplot.imshow(batch_data[i].reshape(28, 28), cmap=pyplot.get_cmap(\'gray\'))
    pyplot.show()
    break      

  生成結果為:

深度學習基礎系列(十一)| Keras中圖像增強技術詳解

  特征标準化

  特征标準化的含義是使圖檔的像素均值為0,标準差為1,不過我試了多次,直覺效果不明顯。

from keras.datasets import mnist
from keras.preprocessing.image import ImageDataGenerator
from matplotlib import pyplot
from keras import backend as K

K.set_image_dim_ordering(\'th\')

(train_data, train_label), (test_data, test_label) = mnist.load_data()
train_data = train_data.reshape(train_data.shape[0], 1, 28, 28)
train_data = train_data.astype(\'float32\')

# 建立圖像生成器,指定對圖像操作的内容,允許圖檔标準化處理
datagen = ImageDataGenerator(featurewise_center=True, featurewise_std_normalization=True)
# 圖像生成器要訓練的資料
datagen.fit(train_data)

# 這是個圖像生成疊代器,是可以無限生成各種新圖檔,我們指定每輪疊代隻生成9張圖檔
for batch_data, batch_label in datagen.flow(train_data, train_label, batch_size=9):
    for i in range(0, 9):
        # 建立一個 3*3的九宮格,以顯示圖檔
        pyplot.subplot(330 + 1 + i)
        pyplot.imshow(batch_data[i].reshape(28, 28), cmap=pyplot.get_cmap(\'gray\'))
    pyplot.show()
    break      

  生成結果為:

深度學習基礎系列(十一)| Keras中圖像增強技術詳解

  就個人而言,我傾向于在圖像增強中使用旋轉、亮度調整、翻轉和平移操作。

二、Keras如何進行圖像增強資料訓練

  在之前的文章中我已經展現過資料增強的使用。在Keras中,增強圖檔有三種來源:

  • 圖檔來源于已知資料集,如mnist、cifar,資料格式為numpy格式;
  • 圖檔來源于我們自己搜集的圖檔,如本文引入的花類資料集,其圖檔為jpg、png等格式;
  • 圖檔來源于panda資料集;

  其中資料來源已知資料集,其操作方法如下:

(x_train, y_train), (x_test, y_test) = cifar10.load_data()
y_train = np_utils.to_categorical(y_train, num_classes)
y_test = np_utils.to_categorical(y_test, num_classes)

datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True)

#生成器綁定訓練集
datagen.fit(x_train)

# 模型綁定生成器,并不停地疊代産生資料,可指定疊代次數,假設圖檔總數為1000張,batch預設為32,則每次疊代需要産生1000/32=32個步驟
history = model.fit_generator(datagen.flow(x_train, y_train, batch_size=32),
                    steps_per_epoch=len(x_train) / 32, epochs=epochs)      

  資料來源圖檔集,其操作方法如下:

batch_size = 32
# 疊代50次
epochs = 50
# 依照模型規定,圖檔大小被設定為224
IMAGE_SIZE = 224
TRAIN_PATH = \'/home/yourname/Documents/tensorflow/images/17flowerclasses/train\'
TEST_PATH = \'/home/yourname/Documents/tensorflow/images/17flowerclasses/test\'
FLOWER_CLASSES = [\'Bluebell\', \'ButterCup\', \'ColtsFoot\', \'Cowslip\', \'Crocus\', \'Daffodil\', \'Daisy\',\'Dandelion\', \'Fritillary\', \'Iris\', \'LilyValley\', \'Pansy\', \'Snowdrop\', \'Sunflower\',\'Tigerlily\', \'tulip\', \'WindFlower\']

# 使用資料增強
train_datagen = ImageDataGenerator(rotation_range=90)
# 可指定輸出圖檔大小,因為深度學習要求訓練圖檔大小保持一緻
train_generator = train_datagen.flow_from_directory(directory=TRAIN_PATH,
                                                        target_size=(IMAGE_SIZE, IMAGE_SIZE),
                                                        classes=FLOWER_CLASSES)
test_datagen = ImageDataGenerator()
test_generator = test_datagen.flow_from_directory(directory=TEST_PATH, 
                                                      target_size=(IMAGE_SIZE, IMAGE_SIZE),
                                                      classes=FLOWER_CLASSES)
 # 運作模型
history = model.fit_generator(train_generator, epochs=epochs, validation_data=test_generator)      

   需要說明的是,這些增強圖檔都是在記憶體中實時批量疊代生成的,不是一次性被讀入記憶體,這樣可以極大地節約記憶體空間,加快處理速度。若想保留中間過程生成的增強圖檔,可以在上述方法中添加儲存路徑等參數,此處不再贅述。

三、結論

  本文介紹了如何在Keras中使用圖像增強技術,對圖檔可以進行各種操作,以生成數倍于原圖檔的增強圖檔集。這些資料集可幫助我們有效地對抗過拟合問題,更好地生成理想的模型。