1. 程式人生 > 實用技巧 >深度學習-資料集增強-方法

深度學習-資料集增強-方法

Data Augmentation--資料增強解決你有限的資料集

can my “state-of-the-art” neural network perform well with the meagre amount of data I have?

Yes.我們的優化目的,是當引數沿著正確的方向調整時,模型的loss可以達到最低。

How do I get more data, if I don’t have “more data”?

因此,為了獲得更多資料,我們只需要對現有資料集進行微小改動。輕微更改,例如翻轉或翻譯或輪換。無論如何,我們的神經網路會認為這些是不同的影象。


卷積神經網路CNN,對放置在不同方向的物件,也能進行穩健的分類,即具有不變性的屬性。更具體地,CNN對於平移,不同視角,尺度大小或光照等(或上述的組合)可以是不變的。
這基本上是資料增加的前提。在實際場景中,我們可能會在一組有限的條件下獲取影象資料集。但是,我們的目標應用可能存在於各種條件下,例如不同的方向,位置,比例,亮度等。我們通過使用額外的合成對資料進行修改,並訓練我們的神經網路來解釋這些情況。

1、Flip

給你個影象自己體會!!!

# NumPy.'img' = A single image.
flip_1 = np.fliplr(img)
# TensorFlow. 'x' = A placeholder for an image.
shape = [height, width, channels] x = tf.placeholder(dtype = tf.float32, shape = shape) flip_2 = tf.image.flip_up_down(x) flip_3 = tf.image.flip_left_right(x) flip_4 = tf.image.random_flip_up_down(x) flip_5 = tf.image.random_flip_left_right(x)

2、Rotation

關於此操作需要注意的一件事是旋轉後圖像尺寸可能無法保留。如果您的影象是正方形,則以直角旋轉它將保留影象大小。如果它是一個矩形,旋轉180度將保持大小。以更精細的角度旋轉影象也會改變最終的影象尺寸。我們將在下一節中看到我們如何處理這個問題。以下是以直角旋轉的方形影象的示例。


您可以使用您喜歡的包中的任何以下命令執行旋轉。資料增強因子= 2到4倍

# Placeholders: 'x' = A single image, 'y' = A batch of images
# 'k' denotes the number of 90 degree anticlockwise rotations
shape = [height, width, channels]
x = tf.placeholder(dtype = tf.float32, shape = shape)
rot_90 = tf.image.rot90(img, k=1)
rot_180 = tf.image.rot90(img, k=2)
# To rotate in any angle. In the example below, 'angles' is in radians shape = [batch, height, width, 3] y = tf.placeholder(dtype = tf.float32, shape = shape) rot_tf_180 = tf.contrib.image.rotate(y, angles=3.1415)
# Scikit-Image. 'angle' = Degrees. 'img' = Input Image # For details about 'mode', checkout the interpolation section below. rot = skimage.transform.rotate(img, angle=45, mode='reflect')

3、Scale

影象可以向外或向內縮放。向外縮放時,最終影象尺寸將大於原始影象尺寸。大多數影象框架從新影象中剪切出一個部分,其大小等於原始影象。我們將在下一節中處理向內縮放,因為它會縮小影象大小,迫使我們對超出邊界的內容做出假設。以下是縮放的示例或影象。


您可以使用scikit-image使用以下命令執行縮放。資料增強因子=任意。

# Scikit Image. 'img' = Input Image, 'scale' = Scale factor
# For details about 'mode', checkout the interpolation section below.
scale_out = skimage.transform.rescale(img, scale=2.0, mode='constant')
scale_in = skimage.transform.rescale(img, scale=0.5, mode='constant')
# Don't forget to crop the images back to the original size (for 
# scale_out)

4、Crop

與縮放不同,我們只是從原始影象中隨機抽樣一個部分。
然後,我們將此部分的大小調整為原始影象大小。
這種方法通常稱為隨機裁剪。
以下是隨機裁剪的示例。
仔細觀察,您會發現此方法與縮放之間的區別。


您可以使用以下任何TensorFlow命令執行隨機裁剪。資料增強因子=任意。

# TensorFlow. 'x' = A placeholder for an image.
original_size = [height, width, channels]
x = tf.placeholder(dtype = tf.float32, shape = original_size)
# Use the following commands to perform random crops
crop_size = [new_height, new_width, channels]
seed = np.random.randint(1234)
x = tf.random_crop(x, size = crop_size, seed = seed)
output = tf.images.resize_images(x, size = original_size)

5、Translation

翻譯只涉及沿X或Y方向(或兩者)移動影象。在下面的示例中,我們假設影象在其邊界之外具有黑色背景,並且被適當地翻譯。這種增強方法非常有用,因為大多數物件幾乎可以位於影象的任何位置。這迫使你的卷積神經網路無處不在。


您可以使用以下命令在TensorFlow中執行轉換。
資料增強因子=任意

# pad_left, pad_right, pad_top, pad_bottom denote the pixel 
# displacement. Set one of them to the desired value and rest to 0
shape = [batch, height, width, channels]
x = tf.placeholder(dtype = tf.float32, shape = shape)
# We use two functions to get our desired augmentation
x = tf.image.pad_to_bounding_box(x, pad_top, pad_left, height + pad_bottom + pad_top, width + pad_right + pad_left)
output = tf.image.crop_to_bounding_box(x, pad_bottom, pad_right, height, width)

6、Gaussion Noise

當您的神經網路試圖學習可能無用的高頻特徵(大量出現的模式)時,通常會發生過度擬合。具有零均值的高斯噪聲基本上在所有頻率中具有資料點,從而有效地扭曲高頻特徵。這也意味著較低頻率的元件(通常是您的預期資料)也會失真,但您的神經網路可以學會超越它。新增適量的噪音可以增強學習能力。一個色調較低的版本是鹽和胡椒噪音,它表現為隨機的黑白畫素在影象中傳播。這類似於通過向影象新增高斯噪聲而產生的效果,但可能具有較低的資訊失真水平。


您可以在TensorFlow上使用以下命令為影象新增高斯噪聲。資料增強因子= 2x。

#TensorFlow. 'x' = A placeholder for an image.
shape = [height, width, channels]
x = tf.placeholder(dtype = tf.float32, shape = shape)
# Adding Gaussian noise
noise = tf.random_normal(shape=tf.shape(x), mean=0.0, stddev=1.0,
dtype=tf.float32)
output = tf.add(x, noise)

Advanced Augmentation Techniques高階增強技術

現實世界中,原始資料仍然可以存在於上述簡單方法無法解釋的各種條件下。例如,識別照片中景觀(山水)。景觀可以是任何東西:冰苔原,草原,森林等。聽起來像一個非常直接的分類任務吧?除了一件事,你是對的。我們忽略了影響表演的照片中的一個重要特徵 - 拍攝照片的季節。
如果我們的神經網路不瞭解某些景觀可以在各種條件下(雪,潮溼,明亮等)存在的事實,它可能會將冰凍的湖岸錯誤地標記為冰川或將溼地標記為沼澤。
緩解這種情況的一種方法是新增更多圖片,以便我們考慮所有季節性變化。但這是一項艱鉅的任務。擴充套件我們的資料增強概念,想象一下人工生成不同季節的效果有多酷?

GAN來拯救你

在沒有加入細節的情況下,條件GAN可以將影象從一個域轉換為影象到另一個域。如果你認為這聽起來太模糊,No;這就是這個神經網路的強大功能!以下是用於將夏季風景照片轉換為冬季風景的條件GAN的示例。


Changing seasons using a CycleGAN(Source)
上述方法是穩健的,但計算密集。更便宜的替代品將被稱為神經風格轉移。它抓取一個影象(又稱“風格”)的紋理/氛圍/外觀,並將其與另一個影象的內容混合。使用這種強大的技術,我們產生類似於條件GAN的效果(事實上,這種方法是在cGAN發明之前引入的!)。
這種方法的唯一缺點是,輸出看起來更具藝術性而非現實性。但是,有一些進步,如下面顯示的深度照片風格轉移,有令人印象深刻的結果。


深度照片風格轉移。請注意我們如何在資料集上生成我們想要的效果。(來源
我們沒有深入探索這些技術,因為我們並不關心它們的內在工作。我們可以使用現有的訓練模型,以及轉移學習的魔力,將其用於增強。

A brief note on interpolation關於插值的簡要說明

如果您想要翻譯不具有黑色背景的影象,該怎麼辦?如果你想向內擴充套件怎麼辦?或者以更精細的角度旋轉?在我們執行這些轉換後,我們需要保留原始影象大小。由於我們的影象沒有關於其邊界之外的任何資訊,我們需要做出一些假設。通常,假設影象邊界之外的空間在每個點都是常數0。因此,當您進行這些轉換時,會得到一個未定義影象的黑色區域。


從左側開始,影象逆時針旋轉45度,影象向右旋轉,影象向內縮放。
**但這是正確的假設嗎?**在現實世界的情況下,大多數不是。影象處理和ML框架有一些標準方法,您可以使用它們來決定如何填充未知空間。它們的定義如下。


從左邊開始,我們有constant, edge, reflect, symmetric and wrap模式。

1、Constant

最簡單的插值方法是用一些常數值填充未知區域。這可能不適用於自然影象,但可以用於在單色背景下拍攝的影象。

2、Edge

在邊界之後擴充套件影象的邊緣值。此方法適用於溫和的translations。

3、Relect

影象畫素值沿影象邊界反射。此方法適用於包含樹木,山脈等的連續或自然背景。

4、Symmetric對稱

該方法類似於反射,除了在反射邊界處製作邊緣畫素的副本的事實。通常,反射和對稱可以互換使用,但在處理非常小的影象或圖案時會出現差異。

5、Wrap

影象只是重複超出其邊界,就好像它正在平鋪一樣。這種方法並不像其他方法那樣普遍使用,因為它對很多場景都沒有意義。
除此之外,您可以設計自己的方法來處理未定義的空間,但通常這些方法對大多數分類問題都可以。

So, if I use ALL of these techniques, my ML algorithm would be robust right?

如果你以正確的方式使用它,那麼是的!你問的正確方法是什麼?好吧,有時並非所有的增強技術都對資料集有意義。再考慮我們的汽車示例。以下是一些修改影象的方法。


第一幅影象(左起)是原始影象,第二張影象是水平翻轉,第三張影象旋轉180度,最後一張影象旋轉90度(順時針)。
當然,它們是同一輛車的照片,但您的目標應用可能永遠不會看到以這些方向呈現的汽車。
例如,如果您只是想在路上對隨機汽車進行分類,那麼只有第二張影象才能在資料集上進行分類。但是,如果你擁有一家處理車禍的保險公司,並且你想要確定倒車,破車的車型,那麼第三張圖片就有意義了。對於上述兩種情況,最後一張影象可能沒有意義。
關鍵是,在使用增強技術時,我們必須確保不增加不相關的資料。

Is it really worth the effort?

你可能期待一些結果來激勵你走得更遠。很公平;我也有這個問題。讓我用玩具示例證明增強確實有效。您可以複製此實驗以進行驗證。
讓我們建立兩個神經網路,將資料分類為四類中的一類:貓,獅子,老虎或豹子。問題是,一個不會使用資料增加,而另一個則不會。您可以從此處下載資料集link。(ps:需要翻牆,打不開的可留郵箱給我)
如果你已經檢查了資料集,你會發現每個類只有50個影象用於訓練和測試。顯然,我們不能對其中一個分類器使用擴充。為了使賠率更公平,我們使用Transfer Learning為模型提供了更少的資料量。


對於沒有增強的那個,讓我們使用VGG19網路。我在這裡寫了一個TensorFlow實現,它基於here這個實現。一旦你克隆了我的倉庫,就可以從這裡(同上data)獲取資料集,並從這裡獲取vgg19.npy(用於轉移學習)。您現在可以執行模型來驗證效能。
我同意,編寫額外的資料擴充程式碼確實是一種努力。所以,為了建立我們的第二個模型,我轉向Nanonets。他們在內部使用轉移學習和資料擴充,以使用最少的資料提供最佳結果。您需要做的就是在他們的網站上傳資料,並等待它們在他們的伺服器上訓練(通常大約30分鐘)。你知道什麼,它對我們的比較實驗來說是完美的。
完成培訓後,您可以請求呼叫其API來計算測試準確度。檢視我的倉庫以獲取示例程式碼段(不要忘記在程式碼段中插入您的模型ID)。

Results
VGG19 (No Augmentation)- 76% Test Accuracy (Highest)
Nanonets (With Augmentation) - 94.5% Test Accuracy

令人印象深刻的不是它。事實上,大多數模型在更多資料的情況下表現良好。所以為了提供一個具體的證明,我已經提到了下表。它顯示了Cifar 10(C10)和Cifar 100(C100)資料集上流行神經網路的錯誤率。C10 +和C100 +列是資料增加的錯誤率。