| 撰寫/攝影 | CH.Tseng |
| 部落格 | https://chtseng.wordpress.com/ |
| https://www.facebook.com/chenghsun.tseng |
- Review並重新組合或調整model架構。
- 將資料進行正規化,如L1/L2 regularization。
- 使用dropout技術。
- 使用Data augmentation(資料增強)技術。
dropout技術在之前已介紹並實際應用過,在此所要介紹的是Data augmentation。不同於Dropout透過丟棄一定比例的神經元以模擬不同的dataset,Data augmentation則是從既有的dataset中產生出更多的資料讓系統去學習,說坦白一點,是創造更多的「假」資料,來彌補我們資料不足的缺憾。
雖然是假的資料,但也是從原始資料內容修改產生的,因此Data augmentation經過證實的確可解決資料不足的困境並提昇系統訓練的準確率哦!我們來看看要怎麼使用它。
Data augmentation原理
一張圖片經過旋轉、調整大小、比例尺寸,或者改變亮度色溫、翻轉等處理後,我們人眼仍能辨識出來是相同的相片,但是對機器來說那可是完全不同的新圖像了,因此, Data augmentation就是將dataset中既有的圖片予以修改變形,以創造出更多的圖片來讓機器學習,彌補資料量不足的困擾。
Keras透過ImageDataGenerator class提供Data augmentation相關的功能,如:
- 資料的正規化normalization:可針對Sample-wise(每次取樣的sample batch)或Feature-wise(整體的dataset)
- 資料白化(Whitening)處理:提供ZCA Whitening處理。(Whitening是一種將資料去冗餘的技術)
- 影像處理:翻轉、旋轉、切裁、放大縮小、偏移…等。
更詳細的參數使用請參考https://keras.io/preprocessing/image/。
如何使用Data augmentation
在Keras使用Data augmentation的流程是:
1.載入class:
[pastacode lang=”markup” manual=”from%20keras.preprocessing.image%20import%20ImageDataGenerator” message=”” highlight=”” provider=”manual”/]2.初始化ImageDataGenerator物件,並定義其參數:
[pastacode lang=”markup” manual=”datagen%20%3D%20ImageDataGenerator(%0A%0A%20%20%20%20zca_whitening%3DFalse%2C%0A%0A%20%20%20%20rotation_range%3D40%2C%0A%0A%20%20%20%20width_shift_range%3D0.2%2C%0A%0A%20%20%20%20height_shift_range%3D0.2%2C%0A%0A%20%20%20%20shear_range%3D0.2%2C%0A%0A%20%20%20%20zoom_range%3D0.2%2C%0A%0A%20%20%20%20horizontal_flip%3DTrue%2C%0A%0A%20%20%20%20fill_mode%3D%E2%80%99nearest%E2%80%99)” message=”” highlight=”” provider=”manual”/]3.產生不同的圖形,以下分成兩種狀況來說明:
A)想要產生圖形檔到disk:
- 例如要從某張相片產生10張檔名開頭為cat的jpg圖片,並儲存到目錄preview中:
B)想要在訓練時邊產生圖形:
這又分兩種情況,一種是dataset已載入memory,另一種是dataset放在某實體目錄中尚未讀入。
- dataset已載入memory:
- dataset位在data/train目錄下:
Data augmentation的效果
下方範例為讀入一張圖片,然後透過Data augmentation來產生不同的圖片為例,您可以同步開啟https://github.com/ch-tseng/data-augmentation-Keras/blob/master/DataAugmentation-1.ipynb 來檢視其效果
- 載入相關class及module

- 指定一張相片
![]()
- 讀入指定相片:
使用opencv讀入圖片,由於opencv預設格式為BGR,因此需用cvtColor轉為RGB格式。
[pastacode lang=”markup” manual=”img%20%3D%20cv2.imread(imgForTest)%0A%0Aimg%20%3D%20cv2.cvtColor(img%2C%20cv2.COLOR_BGR2RGB)” message=”” highlight=”” provider=”manual”/]
- 顯示圖片及其資料維度:
由於我們是load單張圖片而非array,因此需要修改其dimention,在前方加入ID項次。
[pastacode lang=”markup” manual=”plt.imshow(img)%0A%0Aprint(img.shape)%0A%0Aimg%20%3D%20img.reshape((1%2C)%20%2B%20img.shape)%0A%0Aprint(img.shape)” message=”” highlight=”” provider=”manual”/]

- 定義相關參數:
您可以看到下方的ImageDataGenerator參數值有rotation、shift、shear、flip、zoom、fill_mode…等,從字義上即可瞭解其圖形效果,相關詳細參數說明請參考:https://keras.io/preprocessing/image/
[pastacode lang=”markup” manual=”datagen%20%3D%20ImageDataGenerator(%20%20%20%20%0A%0A%20%20%20%20rotation_range%3D40%2C%0A%0A%20%20%20%20width_shift_range%3D0.2%2C%0A%0A%20%20%20%20height_shift_range%3D0.2%2C%0A%0A%20%20%20%20shear_range%3D0.2%2C%0A%0A%20%20%20%20zoom_range%3D0.2%2C%0A%0A%20%20%20%20horizontal_flip%3DTrue%2C%0A%0A%20%20%20%20fill_mode%3D%E2%80%99nearest%E2%80%99)” message=”” highlight=”” provider=”manual”/]
- 經由augmentation產生各種圖形:
datagen.flow會依據指定參數產生各式圖形,您可以輸入一個圖形陣列或本範例一樣的單張圖片。
[pastacode lang=”markup” manual=”%0A%20%20%20%20%20%20%20%20%E5%9C%A8%E9%80%B2%E8%A1%8C%E6%B7%B1%E5%BA%A6%E5%AD%B8%E7%BF%92%E8%A8%93%E7%B7%B4%E6%99%82%EF%BC%8C%E6%88%91%E5%80%91%E7%B6%93%E5%B8%B8%E9%9C%80%E8%A6%81%E6%B5%B7%E9%87%8F%E7%9A%84%E8%B3%87%E6%96%99%E4%BB%A5%E7%A2%BA%E4%BF%9D%E8%A8%93%E7%B7%B4%E6%99%82%E4%B8%8D%E6%9C%83%E7%94%A2%E7%94%9F%E9%81%8E%E5%BA%A6%E6%93%AC%E5%90%88%EF%BC%88over-fitting%EF%BC%89%E7%9A%84%E7%8F%BE%E8%B1%A1%EF%BC%8C%E7%84%B6%E8%80%8C%E5%9C%A8%E7%8F%BE%E4%BB%8A%E6%95%B8%E4%BD%8D%E6%99%82%E4%BB%A3%EF%BC%8C%E8%B3%87%E6%96%99%E5%8F%AF%E6%98%AF%E9%A9%85%E4%BD%BFAI%E5%BC%95%E6%93%8E%E5%85%A8%E5%8A%9B%E9%81%8B%E8%BD%89%E7%9A%84%E6%96%B0%E7%9F%B3%E6%B2%B9%EF%BC%8C%E6%AF%8F%E5%AE%B6%E5%85%AC%E5%8F%B8%E8%8E%AB%E4%B8%8D%E7%B4%9B%E6%B1%82%E8%B3%87%E6%96%99%E8%8B%A5%E6%B8%B4%EF%BC%8C%E5%B0%8E%E8%87%B4%E5%A4%A7%E9%83%A8%E4%BB%BD%E6%9C%89%E5%83%B9%E5%80%BC%E7%9A%84%E8%B3%87%E6%96%99%E9%83%BD%E6%8E%8C%E6%8F%A1%E5%9C%A8%E8%B3%87%E9%87%91%E9%9B%84%E5%8E%9A%E5%85%AC%E5%8F%B8%E6%88%96%E4%BD%8D%E6%96%BC%E7%9B%B8%E9%97%9C%E9%A0%98%E5%9F%9F%E7%9A%84%E4%BC%81%E6%A5%AD%EF%BC%8C%E5%80%8B%E4%BA%BA%E9%96%8B%E7%99%BC%E8%80%85%E6%88%96%E6%99%AE%E9%80%9A%E5%85%AC%E5%8F%B8%E5%BE%88%E9%9B%A3%E6%93%81%E6%9C%89%E6%88%96%E8%80%85%E6%90%9C%E9%9B%86%E5%AE%8C%E6%95%B4%E9%9C%80%E8%A6%81%E7%9A%84%E8%B3%87%E6%96%99%E3%80%82%E5%9B%A0%E6%AD%A4%EF%BC%8C%E4%B8%80%E8%88%AC%E6%88%91%E5%80%91%E6%9C%83%E6%8E%A1%E5%8F%96%E5%A6%82%E4%B8%8B%E7%9A%84%E4%BD%9C%E6%B3%95%EF%BC%8C%E4%BB%A5%E8%A3%9C%E8%B6%B3%E8%B3%87%E6%96%99%E4%B8%8D%E8%B6%B3%E8%80%8C%E5%B0%8E%E8%87%B4%E7%9A%84over-fitting%E5%95%8F%E9%A1%8C%EF%BC%9A%0AReview%E4%B8%A6%E9%87%8D%E6%96%B0%E7%B5%84%E5%90%88%E6%88%96%E8%AA%BF%E6%95%B4model%E6%9E%B6%E6%A7%8B%E3%80%82%0A%E5%B0%87%E8%B3%87%E6%96%99%E9%80%B2%E8%A1%8C%E6%AD%A3%E8%A6%8F%E5%8C%96%EF%BC%8C%E5%A6%82L1%2FL2%20regularization%E3%80%82%0A%E4%BD%BF%E7%94%A8dropout%E6%8A%80%E8%A1%93%E3%80%82%0A%E4%BD%BF%E7%94%A8Data%20augmentation%EF%BC%88%E8%B3%87%E6%96%99%E5%A2%9E%E5%BC%B7%EF%BC%89%E6%8A%80%E8%A1%93%E3%80%82%0Adropout%E6%8A%80%E8%A1%93%E5%9C%A8%E4%B9%8B%E5%89%8D%E5%B7%B2%E4%BB%8B%E7%B4%B9%E4%B8%A6%E5%AF%A6%E9%9A%9B%E6%87%89%E7%94%A8%E9%81%8E%EF%BC%8C%E5%9C%A8%E6%AD%A4%E6%89%80%E8%A6%81%E4%BB%8B%E7%B4%B9%E7%9A%84%E6%98%AFData%20augmentation%E3%80%82%E4%B8%8D%E5%90%8C%E6%96%BCDropout%E9%80%8F%E9%81%8E%E4%B8%9F%E6%A3%84%E4%B8%80%E5%AE%9A%E6%AF%94%E4%BE%8B%E7%9A%84%E7%A5%9E%E7%B6%93%E5%85%83%E4%BB%A5%E6%A8%A1%E6%93%AC%E4%B8%8D%E5%90%8C%E7%9A%84dataset%EF%BC%8CData%20augmentation%E5%89%87%E6%98%AF%E5%BE%9E%E6%97%A2%E6%9C%89%E7%9A%84dataset%E4%B8%AD%E7%94%A2%E7%94%9F%E5%87%BA%E6%9B%B4%E5%A4%9A%E7%9A%84%E8%B3%87%E6%96%99%E8%AE%93%E7%B3%BB%E7%B5%B1%E5%8E%BB%E5%AD%B8%E7%BF%92%EF%BC%8C%E8%AA%AA%E5%9D%A6%E7%99%BD%E4%B8%80%E9%BB%9E%EF%BC%8C%E6%98%AF%E5%89%B5%E9%80%A0%E6%9B%B4%E5%A4%9A%E7%9A%84%E3%80%8C%E5%81%87%E3%80%8D%E8%B3%87%E6%96%99%EF%BC%8C%E4%BE%86%E5%BD%8C%E8%A3%9C%E6%88%91%E5%80%91%E8%B3%87%E6%96%99%E4%B8%8D%E8%B6%B3%E7%9A%84%E7%BC%BA%E6%86%BE%E3%80%82%0A%0A%20%20%20%20%20%20%20%20%E9%9B%96%E7%84%B6%E6%98%AF%E5%81%87%E7%9A%84%E8%B3%87%E6%96%99%EF%BC%8C%E4%BD%86%E4%B9%9F%E6%98%AF%E5%BE%9E%E5%8E%9F%E5%A7%8B%E8%B3%87%E6%96%99%E5%85%A7%E5%AE%B9%E4%BF%AE%E6%94%B9%E7%94%A2%E7%94%9F%E7%9A%84%EF%BC%8C%E5%9B%A0%E6%AD%A4Data%20augmentation%E7%B6%93%E9%81%8E%E8%AD%89%E5%AF%A6%E7%9A%84%E7%A2%BA%E5%8F%AF%E8%A7%A3%E6%B1%BA%E8%B3%87%E6%96%99%E4%B8%8D%E8%B6%B3%E7%9A%84%E5%9B%B0%E5%A2%83%E4%B8%A6%E6%8F%90%E6%98%87%E7%B3%BB%E7%B5%B1%E8%A8%93%E7%B7%B4%E7%9A%84%E6%BA%96%E7%A2%BA%E7%8E%87%E5%93%A6%EF%BC%81%E6%88%91%E5%80%91%E4%BE%86%E7%9C%8B%E7%9C%8B%E8%A6%81%E6%80%8E%E9%BA%BC%E4%BD%BF%E7%94%A8%E5%AE%83%E3%80%82%0A%0AData%20augmentation%E5%8E%9F%E7%90%86%0A%0A%E4%B8%80%E5%BC%B5%E5%9C%96%E7%89%87%E7%B6%93%E9%81%8E%E6%97%8B%E8%BD%89%E3%80%81%E8%AA%BF%E6%95%B4%E5%A4%A7%E5%B0%8F%E3%80%81%E6%AF%94%E4%BE%8B%E5%B0%BA%E5%AF%B8%EF%BC%8C%E6%88%96%E8%80%85%E6%94%B9%E8%AE%8A%E4%BA%AE%E5%BA%A6%E8%89%B2%E6%BA%AB%E3%80%81%E7%BF%BB%E8%BD%89%E7%AD%89%E8%99%95%E7%90%86%E5%BE%8C%EF%BC%8C%E6%88%91%E5%80%91%E4%BA%BA%E7%9C%BC%E4%BB%8D%E8%83%BD%E8%BE%A8%E8%AD%98%E5%87%BA%E4%BE%86%E6%98%AF%E7%9B%B8%E5%90%8C%E7%9A%84%E7%9B%B8%E7%89%87%EF%BC%8C%E4%BD%86%E6%98%AF%E5%B0%8D%E6%A9%9F%E5%99%A8%E4%BE%86%E8%AA%AA%E9%82%A3%E5%8F%AF%E6%98%AF%E5%AE%8C%E5%85%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E6%96%B0%E5%9C%96%E5%83%8F%E4%BA%86%EF%BC%8C%E5%9B%A0%E6%AD%A4%EF%BC%8C%20Data%20augmentation%E5%B0%B1%E6%98%AF%E5%B0%87dataset%E4%B8%AD%E6%97%A2%E6%9C%89%E7%9A%84%E5%9C%96%E7%89%87%E4%BA%88%E4%BB%A5%E4%BF%AE%E6%94%B9%E8%AE%8A%E5%BD%A2%EF%BC%8C%E4%BB%A5%E5%89%B5%E9%80%A0%E5%87%BA%E6%9B%B4%E5%A4%9A%E7%9A%84%E5%9C%96%E7%89%87%E4%BE%86%E8%AE%93%E6%A9%9F%E5%99%A8%E5%AD%B8%E7%BF%92%EF%BC%8C%E5%BD%8C%E8%A3%9C%E8%B3%87%E6%96%99%E9%87%8F%E4%B8%8D%E8%B6%B3%E7%9A%84%E5%9B%B0%E6%93%BE%E3%80%82%0A%0A%20%20%20%20%20%20%20%20Keras%E9%80%8F%E9%81%8EImageDataGenerator%20class%E6%8F%90%E4%BE%9BData%20augmentation%E7%9B%B8%E9%97%9C%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%A6%82%EF%BC%9A%0A%0A%E8%B3%87%E6%96%99%E7%9A%84%E6%AD%A3%E8%A6%8F%E5%8C%96normalization%EF%BC%9A%E5%8F%AF%E9%87%9D%E5%B0%8DSample-wise%EF%BC%88%E6%AF%8F%E6%AC%A1%E5%8F%96%E6%A8%A3%E7%9A%84sample%20batch%EF%BC%89%E6%88%96Feature-wise%EF%BC%88%E6%95%B4%E9%AB%94%E7%9A%84dataset%EF%BC%89%0A%E8%B3%87%E6%96%99%E7%99%BD%E5%8C%96%EF%BC%88Whitening%EF%BC%89%E8%99%95%E7%90%86%EF%BC%9A%E6%8F%90%E4%BE%9BZCA%20Whitening%E8%99%95%E7%90%86%E3%80%82%EF%BC%88Whitening%E6%98%AF%E4%B8%80%E7%A8%AE%E5%B0%87%E8%B3%87%E6%96%99%E5%8E%BB%E5%86%97%E9%A4%98%E7%9A%84%E6%8A%80%E8%A1%93%EF%BC%89%0A%E5%BD%B1%E5%83%8F%E8%99%95%E7%90%86%EF%BC%9A%E7%BF%BB%E8%BD%89%E3%80%81%E6%97%8B%E8%BD%89%E3%80%81%E5%88%87%E8%A3%81%E3%80%81%E6%94%BE%E5%A4%A7%E7%B8%AE%E5%B0%8F%E3%80%81%E5%81%8F%E7%A7%BB%E2%80%A6%E7%AD%89%E3%80%82%0A%E6%9B%B4%E8%A9%B3%E7%B4%B0%E7%9A%84%E5%8F%83%E6%95%B8%E4%BD%BF%E7%94%A8%E8%AB%8B%E5%8F%83%E8%80%83https%3A%2F%2Fkeras.io%2Fpreprocessing%2Fimage%2F%E3%80%82%0A%0A%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8Data%20augmentation%0A%20%20%20%20%20%20%20%20%E5%9C%A8Keras%E4%BD%BF%E7%94%A8Data%20augmentation%E7%9A%84%E6%B5%81%E7%A8%8B%E6%98%AF%EF%BC%9A%0A%0A%E8%BC%89%E5%85%A5class%EF%BC%9A%0Afrom%20keras.preprocessing.image%20import%20ImageDataGenerator%0A%0A%E5%88%9D%E5%A7%8B%E5%8C%96ImageDataGenerator%E7%89%A9%E4%BB%B6%EF%BC%8C%E4%B8%A6%E5%AE%9A%E7%BE%A9%E5%85%B6%E5%8F%83%E6%95%B8%3A%0Adatagen%20%3D%20ImageDataGenerator(%0A%0A%20%20%20%20zca_whitening%3DFalse%2C%0A%0A%20%20%20%20rotation_range%3D40%2C%0A%0A%20%20%20%20width_shift_range%3D0.2%2C%0A%0A%20%20%20%20height_shift_range%3D0.2%2C%0A%0A%20%20%20%20shear_range%3D0.2%2C%0A%0A%20%20%20%20zoom_range%3D0.2%2C%0A%0A%20%20%20%20horizontal_flip%3DTrue%2C%0A%0A%20%20%20%20fill_mode%3D%E2%80%99nearest%E2%80%99)%0A%0A%E7%94%A2%E7%94%9F%E4%B8%8D%E5%90%8C%E7%9A%84%E5%9C%96%E5%BD%A2%EF%BC%8C%E4%BB%A5%E4%B8%8B%E5%88%86%E6%88%90%E5%85%A9%E7%A8%AE%E7%8B%80%E6%B3%81%E4%BE%86%E8%AA%AA%E6%98%8E%EF%BC%9A%0A%EF%BC%A1%EF%BC%89%E6%83%B3%E8%A6%81%E7%94%A2%E7%94%9F%E5%9C%96%E5%BD%A2%E6%AA%94%E5%88%B0disk%EF%BC%9A%0A%0A%E4%BE%8B%E5%A6%82%E8%A6%81%E5%BE%9E%E6%9F%90%E5%BC%B5%E7%9B%B8%E7%89%87%E7%94%A2%E7%94%9F10%E5%BC%B5%E6%AA%94%E5%90%8D%E9%96%8B%E9%A0%AD%E7%82%BAcat%E7%9A%84jpg%E5%9C%96%E7%89%87%EF%BC%8C%E4%B8%A6%E5%84%B2%E5%AD%98%E5%88%B0%E7%9B%AE%E9%8C%84preview%E4%B8%AD%EF%BC%9A%0Aimg%20%3D%20cv2.imread(%E2%80%9Ctest1.jpg%E2%80%9D)%0A%0Aimg%20%3D%20cv2.cvtColor(img%2C%20cv2.COLOR_BGR2RGB)%0A%0A%23%E6%A0%BC%E5%BC%8F%E5%BF%85%E9%A0%88%E7%82%BA%EF%BC%9A(sample%E6%95%B8%2C%20channels%2C%20height%2C%20width)%0A%0Aimg%20%3D%20img.reshape((1%2C)%20%2B%20img.shape)%0A%0Afor%20batch%20in%20datagen.flow(img%2C%20batch_size%3D10%2C%0A%0Asave_to_dir%3D%E2%80%99preview%E2%80%99%2C%20save_prefix%3D%E2%80%99cat%E2%80%99%2C%20save_format%3D%E2%80%99jpeg%E2%80%99)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%EF%BC%A2%EF%BC%89%E6%83%B3%E8%A6%81%E5%9C%A8%E8%A8%93%E7%B7%B4%E6%99%82%E9%82%8A%E7%94%A2%E7%94%9F%E5%9C%96%E5%BD%A2%EF%BC%9A%0A%0A%E9%80%99%E5%8F%88%E5%88%86%E5%85%A9%E7%A8%AE%E6%83%85%E6%B3%81%EF%BC%8C%E4%B8%80%E7%A8%AE%E6%98%AFdataset%E5%B7%B2%E8%BC%89%E5%85%A5memory%EF%BC%8C%E5%8F%A6%E4%B8%80%E7%A8%AE%E6%98%AFdataset%E6%94%BE%E5%9C%A8%E6%9F%90%E5%AF%A6%E9%AB%94%E7%9B%AE%E9%8C%84%E4%B8%AD%E5%B0%9A%E6%9C%AA%E8%AE%80%E5%85%A5%E3%80%82%0A%0Adataset%E5%B7%B2%E8%BC%89%E5%85%A5memory%EF%BC%9A%0Adatagen.fit(trainData)%0A%0Atrain_history%20%3D%20model.fit_generator(train_datagen.flow(trainData%2C%20%20%0A%0A%20%20%20%20%20%20trainLabels_hot%2C%20batch_size%3D64)%2C%0A%0A%20%20%20%20%20%20steps_per_epoch%3Dround(len(trainData)%2F64)%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20epochs%3D50%2C%20validation_data%3D(valiData%2C%20valiLabels_hot))%0A%0Adataset%E4%BD%8D%E5%9C%A8data%2Ftrain%E7%9B%AE%E9%8C%84%E4%B8%8B%EF%BC%9A%0AtrainData%20%3D%20train_datagen.flow_from_directory(%0A%0A%20%20%20%20%20%20%20%20%E2%80%9Cdata%2Ftrain%E2%80%9D%2C%0A%0A%20%20%20%20%20%20%20%20target_size%3D(150%2C%20150)%2C%20%20%23%E5%8F%AF%E4%BB%A5%E5%9C%A8%E6%AD%A4%E6%8C%87%E5%AE%9A%E8%A6%81rescale%E7%9A%84%E5%B0%BA%E5%AF%B8%0A%0A%20%20%20%20%20%20%20%20batch_size%3D64%2C%0A%0A%20%20%20%20%20%20%20%20class_mode%3D%E2%80%99binary%E2%80%99)%0A%0Amodel.fit_generator(%0A%0A%20%20%20%20%20%20%20%20trainData%2C%0A%0A%20%20%20%20%20%20%20%20steps_per_epoch%3D%20round(len(trainData)%2F64)%2C%0A%0A%20%20%20%20%20%20%20%20epochs%3D50%2C%0A%0Avalidation_data%3D(valiData%2C%20valiLabels_hot)%20)%0A%0AData%20augmentation%E7%9A%84%E6%95%88%E6%9E%9C%0A%E4%B8%8B%E6%96%B9%E7%AF%84%E4%BE%8B%E7%82%BA%E8%AE%80%E5%85%A5%E4%B8%80%E5%BC%B5%E5%9C%96%E7%89%87%EF%BC%8C%E7%84%B6%E5%BE%8C%E9%80%8F%E9%81%8EData%20augmentation%E4%BE%86%E7%94%A2%E7%94%9F%E4%B8%8D%E5%90%8C%E7%9A%84%E5%9C%96%E7%89%87%E7%82%BA%E4%BE%8B%EF%BC%8C%E6%82%A8%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%AD%A5%E9%96%8B%E5%95%9Fhttps%3A%2F%2Fgithub.com%2Fch-tseng%2Fdata-augmentation-Keras%2Fblob%2Fmaster%2FDataAugmentation-1.ipynb%20%E4%BE%86%E6%AA%A2%E8%A6%96%E5%85%B6%E6%95%88%E6%9E%9C%0A%0A%E8%BC%89%E5%85%A5%E7%9B%B8%E9%97%9Cclass%E5%8F%8Amodule%0Aimport%20cv2%0A%0Afrom%20matplotlib%20import%20pyplot%20as%20plt%0A%0A%25matplotlib%20inline%0A%0Afrom%20pylab%20import%20rcParams%0A%0ArcParams%5B%E2%80%98figure.figsize%E2%80%99%5D%20%3D%2015%2C%2015%0A%0Afrom%20keras.preprocessing.image%20import%20ImageDataGenerator%2C%20array_to_img%2C%20img_to_array%2C%20load_img%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp.png%0A%0A%E6%8C%87%E5%AE%9A%E4%B8%80%E5%BC%B5%E7%9B%B8%E7%89%87%0AimgForTest%20%3D%20%E2%80%9C..%2Ftest1.jpg%22%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp0.png%0A%0A%E8%AE%80%E5%85%A5%E6%8C%87%E5%AE%9A%E7%9B%B8%E7%89%87%EF%BC%9A%0A%E4%BD%BF%E7%94%A8opencv%E8%AE%80%E5%85%A5%E5%9C%96%E7%89%87%EF%BC%8C%E7%94%B1%E6%96%BCopencv%E9%A0%90%E8%A8%AD%E6%A0%BC%E5%BC%8F%E7%82%BABGR%EF%BC%8C%E5%9B%A0%E6%AD%A4%E9%9C%80%E7%94%A8cvtColor%E8%BD%89%E7%82%BARGB%E6%A0%BC%E5%BC%8F%E3%80%82%0A%0Aimg%20%3D%20cv2.imread(imgForTest)%0A%0Aimg%20%3D%20cv2.cvtColor(img%2C%20cv2.COLOR_BGR2RGB)%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp3.png%0A%0A%E9%A1%AF%E7%A4%BA%E5%9C%96%E7%89%87%E5%8F%8A%E5%85%B6%E8%B3%87%E6%96%99%E7%B6%AD%E5%BA%A6%EF%BC%9A%0A%E7%94%B1%E6%96%BC%E6%88%91%E5%80%91%E6%98%AFload%E5%96%AE%E5%BC%B5%E5%9C%96%E7%89%87%E8%80%8C%E9%9D%9Earray%EF%BC%8C%E5%9B%A0%E6%AD%A4%E9%9C%80%E8%A6%81%E4%BF%AE%E6%94%B9%E5%85%B6dimention%EF%BC%8C%E5%9C%A8%E5%89%8D%E6%96%B9%E5%8A%A0%E5%85%A5ID%E9%A0%85%E6%AC%A1%E3%80%82%0A%0Aplt.imshow(img)%0A%0Aprint(img.shape)%0A%0Aimg%20%3D%20img.reshape((1%2C)%20%2B%20img.shape)%0A%0Aprint(img.shape)%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp7.png%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp8.png%0A%0A%E5%AE%9A%E7%BE%A9%E7%9B%B8%E9%97%9C%E5%8F%83%E6%95%B8%EF%BC%9A%0A%E6%82%A8%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E4%B8%8B%E6%96%B9%E7%9A%84ImageDataGenerator%E5%8F%83%E6%95%B8%E5%80%BC%E6%9C%89rotation%E3%80%81shift%E3%80%81shear%E3%80%81flip%E3%80%81zoom%E3%80%81fill_mode%E2%80%A6%E7%AD%89%EF%BC%8C%E5%BE%9E%E5%AD%97%E7%BE%A9%E4%B8%8A%E5%8D%B3%E5%8F%AF%E7%9E%AD%E8%A7%A3%E5%85%B6%E5%9C%96%E5%BD%A2%E6%95%88%E6%9E%9C%EF%BC%8C%E7%9B%B8%E9%97%9C%E8%A9%B3%E7%B4%B0%E5%8F%83%E6%95%B8%E8%AA%AA%E6%98%8E%E8%AB%8B%E5%8F%83%E8%80%83%EF%BC%9Ahttps%3A%2F%2Fkeras.io%2Fpreprocessing%2Fimage%2F%0A%0Adatagen%20%3D%20ImageDataGenerator(%20%20%20%20%0A%0A%20%20%20%20rotation_range%3D40%2C%0A%0A%20%20%20%20width_shift_range%3D0.2%2C%0A%0A%20%20%20%20height_shift_range%3D0.2%2C%0A%0A%20%20%20%20shear_range%3D0.2%2C%0A%0A%20%20%20%20zoom_range%3D0.2%2C%0A%0A%20%20%20%20horizontal_flip%3DTrue%2C%0A%0A%20%20%20%20fill_mode%3D%E2%80%99nearest%E2%80%99)%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp9.png%0A%0A%E7%B6%93%E7%94%B1augmentation%E7%94%A2%E7%94%9F%E5%90%84%E7%A8%AE%E5%9C%96%E5%BD%A2%EF%BC%9A%0Adatagen.flow%E6%9C%83%E4%BE%9D%E6%93%9A%E6%8C%87%E5%AE%9A%E5%8F%83%E6%95%B8%E7%94%A2%E7%94%9F%E5%90%84%E5%BC%8F%E5%9C%96%E5%BD%A2%EF%BC%8C%E6%82%A8%E5%8F%AF%E4%BB%A5%E8%BC%B8%E5%85%A5%E4%B8%80%E5%80%8B%E5%9C%96%E5%BD%A2%E9%99%A3%E5%88%97%E6%88%96%E6%9C%AC%E7%AF%84%E4%BE%8B%E4%B8%80%E6%A8%A3%E7%9A%84%E5%96%AE%E5%BC%B5%E5%9C%96%E7%89%87%E3%80%82%0A%0Ai%20%3D%200%0A%0Afor%20batch%20in%20datagen.flow(img%2C%20batch_size%3D10%2C%0A%0A%20%20%20%20%20%20%20%20%20%20save_to_dir%3D%E2%80%99small-2000%2Fpreview%E2%80%99%2C%20save_prefix%3D%E2%80%99cat%E2%80%99%2C%20save_format%3D%E2%80%99jpeg%E2%80%99)%3A%0A%0A%20%20%20%20plt.subplot(5%2C4%2C1%20%2B%20i)%0A%0A%20%20%20%20plt.axis(%E2%80%9Coff%22)%0A%0A%20%20%20%0A%0A%20%20%20%20augImage%20%3D%20batch%5B0%5D%0A%0A%20%20%20%20augImage%20%3D%20augImage.astype(%E2%80%98float32%E2%80%99)%0A%0A%20%20%20%20augImage%20%2F%3D%20255%0A%0A%20%20%20%20plt.imshow(augImage)%0A%0A%20%20%20%0A%0A%20%20%20%20i%20%2B%3D%201%0A%0A%20%20%20%20if%20i%20%3E%2019%3A%0A%0A%20%20%20%20%20%20%20%20break” message=”” highlight=”” provider=”manual”/]

- Review並重新組合或調整model架構。
- 將資料進行正規化,如L1/L2 regularization。
- 使用dropout技術。
- 使用Data augmentation(資料增強)技術。
dropout技術在之前已介紹並實際應用過,在此所要介紹的是Data augmentation。不同於Dropout透過丟棄一定比例的神經元以模擬不同的dataset,Data augmentation則是從既有的dataset中產生出更多的資料讓系統去學習,說坦白一點,是創造更多的「假」資料,來彌補我們資料不足的缺憾。
雖然是假的資料,但也是從原始資料內容修改產生的,因此Data augmentation經過證實的確可解決資料不足的困境並提昇系統訓練的準確率哦!我們來看看要怎麼使用它。
Data augmentation原理
一張圖片經過旋轉、調整大小、比例尺寸,或者改變亮度色溫、翻轉等處理後,我們人眼仍能辨識出來是相同的相片,但是對機器來說那可是完全不同的新圖像了,因此, Data augmentation就是將dataset中既有的圖片予以修改變形,以創造出更多的圖片來讓機器學習,彌補資料量不足的困擾。
Keras透過ImageDataGenerator class提供Data augmentation相關的功能,如:
- 資料的正規化normalization:可針對Sample-wise(每次取樣的sample batch)或Feature-wise(整體的dataset)
- 資料白化(Whitening)處理:提供ZCA Whitening處理。(Whitening是一種將資料去冗餘的技術)
- 影像處理:翻轉、旋轉、切裁、放大縮小、偏移…等。
更詳細的參數使用請參考https://keras.io/preprocessing/image/。
如何使用Data augmentation
在Keras使用Data augmentation的流程是:
- 載入class:
from keras.preprocessing.image import ImageDataGenerator
- 初始化ImageDataGenerator物件,並定義其參數:
datagen = ImageDataGenerator(
zca_whitening=False,
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’)
- 產生不同的圖形,以下分成兩種狀況來說明:
A)想要產生圖形檔到disk:
- 例如要從某張相片產生10張檔名開頭為cat的jpg圖片,並儲存到目錄preview中:
img = cv2.imread(“test1.jpg”)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#格式必須為:(sample數, channels, height, width)
img = img.reshape((1,) + img.shape)
for batch in datagen.flow(img, batch_size=10,
save_to_dir=’preview’, save_prefix=’cat’, save_format=’jpeg’)
B)想要在訓練時邊產生圖形:
這又分兩種情況,一種是dataset已載入memory,另一種是dataset放在某實體目錄中尚未讀入。
- dataset已載入memory:
datagen.fit(trainData)
train_history = model.fit_generator(train_datagen.flow(trainData,
trainLabels_hot, batch_size=64),
steps_per_epoch=round(len(trainData)/64),
epochs=50, validation_data=(valiData, valiLabels_hot))
- dataset位在data/train目錄下:
trainData = train_datagen.flow_from_directory(
“data/train”,
target_size=(150, 150), #可以在此指定要rescale的尺寸
batch_size=64,
class_mode=’binary’)
model.fit_generator(
trainData,
steps_per_epoch= round(len(trainData)/64),
epochs=50,
validation_data=(valiData, valiLabels_hot) )
Data augmentation的效果
下方範例為讀入一張圖片,然後透過Data augmentation來產生不同的圖片為例,您可以同步開啟https://github.com/ch-tseng/data-augmentation-Keras/blob/master/DataAugmentation-1.ipynb 來檢視其效果
- 載入相關class及module
import cv2
from matplotlib import pyplot as plt
%matplotlib inline
from pylab import rcParams
rcParams[‘figure.figsize’] = 15, 15
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img

- 指定一張相片
imgForTest = “../test1.jpg”
![]()
- 讀入指定相片:
使用opencv讀入圖片,由於opencv預設格式為BGR,因此需用cvtColor轉為RGB格式。
img = cv2.imread(imgForTest)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
![]()
- 顯示圖片及其資料維度:
由於我們是load單張圖片而非array,因此需要修改其dimention,在前方加入ID項次。
plt.imshow(img)
print(img.shape)
img = img.reshape((1,) + img.shape)
print(img.shape)


- 定義相關參數:
您可以看到下方的ImageDataGenerator參數值有rotation、shift、shear、flip、zoom、fill_mode…等,從字義上即可瞭解其圖形效果,相關詳細參數說明請參考:https://keras.io/preprocessing/image/
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’)

- 經由augmentation產生各種圖形:
datagen.flow會依據指定參數產生各式圖形,您可以輸入一個圖形陣列或本範例一樣的單張圖片。
i = 0
for batch in datagen.flow(img, batch_size=10,
save_to_dir=’small-2000/preview’, save_prefix=’cat’, save_format=’jpeg’):
plt.subplot(5,4,1 + i)
plt.axis(“off”)
augImage = batch[0]
augImage = augImage.astype(‘float32’)
augImage /= 255
plt.imshow(augImage)
i += 1
if i > 19:
break


同樣的,一張小狗的照片可以產生這麼多的新圖片:https://github.com/ch-tseng/data-augmentation-Keras/blob/master/dogcat-augmentation.ipynb

model.fit與model.fit_generator
注意在使用Data augmentation時,進行訓練所使用的model.fit須改為model.fit_generator才讓系統on-fly的產生新圖像提供訓練使用。model.fit與model.fit_generator這兩個指令都是for相同的訓練用途,但使用時機大有不同:
- model.fit 適用於Dataset已ready,不需再進行任何預處理可直接使用。
- model.fit_generator 適用於Dataset尚未ready,需要在每批次訓練先進行預處理(或產生)。
由於model.fit_generator在每批次訓練前才on demand或on-the-fly處理或產生data,因此能比較有效率的應用在一些硬體資源不太足夠的機器上(例如RAM僅有8G然而dataset卻有1TB的情況),model.fit_generator可避免load整個dataset,只需要在每批次訓練前on-demand產生需要數量的data。
那麼,我們要如何定義要經由Data augmentation產生多少資料呢?最簡單的方式是透過參數samples_per_epoch,該參數定義每次epoch要產生多少sample data(亦即系統在每個epoch所能看到的資料數量)。在下方的例子中,我們設定為training dataset的2倍數量。
[pastacode lang=”markup” manual=”%0A%20%20%20%20%20%20%20%20%E5%9C%A8%E9%80%B2%E8%A1%8C%E6%B7%B1%E5%BA%A6%E5%AD%B8%E7%BF%92%E8%A8%93%E7%B7%B4%E6%99%82%EF%BC%8C%E6%88%91%E5%80%91%E7%B6%93%E5%B8%B8%E9%9C%80%E8%A6%81%E6%B5%B7%E9%87%8F%E7%9A%84%E8%B3%87%E6%96%99%E4%BB%A5%E7%A2%BA%E4%BF%9D%E8%A8%93%E7%B7%B4%E6%99%82%E4%B8%8D%E6%9C%83%E7%94%A2%E7%94%9F%E9%81%8E%E5%BA%A6%E6%93%AC%E5%90%88%EF%BC%88over-fitting%EF%BC%89%E7%9A%84%E7%8F%BE%E8%B1%A1%EF%BC%8C%E7%84%B6%E8%80%8C%E5%9C%A8%E7%8F%BE%E4%BB%8A%E6%95%B8%E4%BD%8D%E6%99%82%E4%BB%A3%EF%BC%8C%E8%B3%87%E6%96%99%E5%8F%AF%E6%98%AF%E9%A9%85%E4%BD%BFAI%E5%BC%95%E6%93%8E%E5%85%A8%E5%8A%9B%E9%81%8B%E8%BD%89%E7%9A%84%E6%96%B0%E7%9F%B3%E6%B2%B9%EF%BC%8C%E6%AF%8F%E5%AE%B6%E5%85%AC%E5%8F%B8%E8%8E%AB%E4%B8%8D%E7%B4%9B%E6%B1%82%E8%B3%87%E6%96%99%E8%8B%A5%E6%B8%B4%EF%BC%8C%E5%B0%8E%E8%87%B4%E5%A4%A7%E9%83%A8%E4%BB%BD%E6%9C%89%E5%83%B9%E5%80%BC%E7%9A%84%E8%B3%87%E6%96%99%E9%83%BD%E6%8E%8C%E6%8F%A1%E5%9C%A8%E8%B3%87%E9%87%91%E9%9B%84%E5%8E%9A%E5%85%AC%E5%8F%B8%E6%88%96%E4%BD%8D%E6%96%BC%E7%9B%B8%E9%97%9C%E9%A0%98%E5%9F%9F%E7%9A%84%E4%BC%81%E6%A5%AD%EF%BC%8C%E5%80%8B%E4%BA%BA%E9%96%8B%E7%99%BC%E8%80%85%E6%88%96%E6%99%AE%E9%80%9A%E5%85%AC%E5%8F%B8%E5%BE%88%E9%9B%A3%E6%93%81%E6%9C%89%E6%88%96%E8%80%85%E6%90%9C%E9%9B%86%E5%AE%8C%E6%95%B4%E9%9C%80%E8%A6%81%E7%9A%84%E8%B3%87%E6%96%99%E3%80%82%E5%9B%A0%E6%AD%A4%EF%BC%8C%E4%B8%80%E8%88%AC%E6%88%91%E5%80%91%E6%9C%83%E6%8E%A1%E5%8F%96%E5%A6%82%E4%B8%8B%E7%9A%84%E4%BD%9C%E6%B3%95%EF%BC%8C%E4%BB%A5%E8%A3%9C%E8%B6%B3%E8%B3%87%E6%96%99%E4%B8%8D%E8%B6%B3%E8%80%8C%E5%B0%8E%E8%87%B4%E7%9A%84over-fitting%E5%95%8F%E9%A1%8C%EF%BC%9A%0AReview%E4%B8%A6%E9%87%8D%E6%96%B0%E7%B5%84%E5%90%88%E6%88%96%E8%AA%BF%E6%95%B4model%E6%9E%B6%E6%A7%8B%E3%80%82%0A%E5%B0%87%E8%B3%87%E6%96%99%E9%80%B2%E8%A1%8C%E6%AD%A3%E8%A6%8F%E5%8C%96%EF%BC%8C%E5%A6%82L1%2FL2%20regularization%E3%80%82%0A%E4%BD%BF%E7%94%A8dropout%E6%8A%80%E8%A1%93%E3%80%82%0A%E4%BD%BF%E7%94%A8Data%20augmentation%EF%BC%88%E8%B3%87%E6%96%99%E5%A2%9E%E5%BC%B7%EF%BC%89%E6%8A%80%E8%A1%93%E3%80%82%0Adropout%E6%8A%80%E8%A1%93%E5%9C%A8%E4%B9%8B%E5%89%8D%E5%B7%B2%E4%BB%8B%E7%B4%B9%E4%B8%A6%E5%AF%A6%E9%9A%9B%E6%87%89%E7%94%A8%E9%81%8E%EF%BC%8C%E5%9C%A8%E6%AD%A4%E6%89%80%E8%A6%81%E4%BB%8B%E7%B4%B9%E7%9A%84%E6%98%AFData%20augmentation%E3%80%82%E4%B8%8D%E5%90%8C%E6%96%BCDropout%E9%80%8F%E9%81%8E%E4%B8%9F%E6%A3%84%E4%B8%80%E5%AE%9A%E6%AF%94%E4%BE%8B%E7%9A%84%E7%A5%9E%E7%B6%93%E5%85%83%E4%BB%A5%E6%A8%A1%E6%93%AC%E4%B8%8D%E5%90%8C%E7%9A%84dataset%EF%BC%8CData%20augmentation%E5%89%87%E6%98%AF%E5%BE%9E%E6%97%A2%E6%9C%89%E7%9A%84dataset%E4%B8%AD%E7%94%A2%E7%94%9F%E5%87%BA%E6%9B%B4%E5%A4%9A%E7%9A%84%E8%B3%87%E6%96%99%E8%AE%93%E7%B3%BB%E7%B5%B1%E5%8E%BB%E5%AD%B8%E7%BF%92%EF%BC%8C%E8%AA%AA%E5%9D%A6%E7%99%BD%E4%B8%80%E9%BB%9E%EF%BC%8C%E6%98%AF%E5%89%B5%E9%80%A0%E6%9B%B4%E5%A4%9A%E7%9A%84%E3%80%8C%E5%81%87%E3%80%8D%E8%B3%87%E6%96%99%EF%BC%8C%E4%BE%86%E5%BD%8C%E8%A3%9C%E6%88%91%E5%80%91%E8%B3%87%E6%96%99%E4%B8%8D%E8%B6%B3%E7%9A%84%E7%BC%BA%E6%86%BE%E3%80%82%0A%0A%20%20%20%20%20%20%20%20%E9%9B%96%E7%84%B6%E6%98%AF%E5%81%87%E7%9A%84%E8%B3%87%E6%96%99%EF%BC%8C%E4%BD%86%E4%B9%9F%E6%98%AF%E5%BE%9E%E5%8E%9F%E5%A7%8B%E8%B3%87%E6%96%99%E5%85%A7%E5%AE%B9%E4%BF%AE%E6%94%B9%E7%94%A2%E7%94%9F%E7%9A%84%EF%BC%8C%E5%9B%A0%E6%AD%A4Data%20augmentation%E7%B6%93%E9%81%8E%E8%AD%89%E5%AF%A6%E7%9A%84%E7%A2%BA%E5%8F%AF%E8%A7%A3%E6%B1%BA%E8%B3%87%E6%96%99%E4%B8%8D%E8%B6%B3%E7%9A%84%E5%9B%B0%E5%A2%83%E4%B8%A6%E6%8F%90%E6%98%87%E7%B3%BB%E7%B5%B1%E8%A8%93%E7%B7%B4%E7%9A%84%E6%BA%96%E7%A2%BA%E7%8E%87%E5%93%A6%EF%BC%81%E6%88%91%E5%80%91%E4%BE%86%E7%9C%8B%E7%9C%8B%E8%A6%81%E6%80%8E%E9%BA%BC%E4%BD%BF%E7%94%A8%E5%AE%83%E3%80%82%0A%0AData%20augmentation%E5%8E%9F%E7%90%86%0A%0A%E4%B8%80%E5%BC%B5%E5%9C%96%E7%89%87%E7%B6%93%E9%81%8E%E6%97%8B%E8%BD%89%E3%80%81%E8%AA%BF%E6%95%B4%E5%A4%A7%E5%B0%8F%E3%80%81%E6%AF%94%E4%BE%8B%E5%B0%BA%E5%AF%B8%EF%BC%8C%E6%88%96%E8%80%85%E6%94%B9%E8%AE%8A%E4%BA%AE%E5%BA%A6%E8%89%B2%E6%BA%AB%E3%80%81%E7%BF%BB%E8%BD%89%E7%AD%89%E8%99%95%E7%90%86%E5%BE%8C%EF%BC%8C%E6%88%91%E5%80%91%E4%BA%BA%E7%9C%BC%E4%BB%8D%E8%83%BD%E8%BE%A8%E8%AD%98%E5%87%BA%E4%BE%86%E6%98%AF%E7%9B%B8%E5%90%8C%E7%9A%84%E7%9B%B8%E7%89%87%EF%BC%8C%E4%BD%86%E6%98%AF%E5%B0%8D%E6%A9%9F%E5%99%A8%E4%BE%86%E8%AA%AA%E9%82%A3%E5%8F%AF%E6%98%AF%E5%AE%8C%E5%85%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E6%96%B0%E5%9C%96%E5%83%8F%E4%BA%86%EF%BC%8C%E5%9B%A0%E6%AD%A4%EF%BC%8C%20Data%20augmentation%E5%B0%B1%E6%98%AF%E5%B0%87dataset%E4%B8%AD%E6%97%A2%E6%9C%89%E7%9A%84%E5%9C%96%E7%89%87%E4%BA%88%E4%BB%A5%E4%BF%AE%E6%94%B9%E8%AE%8A%E5%BD%A2%EF%BC%8C%E4%BB%A5%E5%89%B5%E9%80%A0%E5%87%BA%E6%9B%B4%E5%A4%9A%E7%9A%84%E5%9C%96%E7%89%87%E4%BE%86%E8%AE%93%E6%A9%9F%E5%99%A8%E5%AD%B8%E7%BF%92%EF%BC%8C%E5%BD%8C%E8%A3%9C%E8%B3%87%E6%96%99%E9%87%8F%E4%B8%8D%E8%B6%B3%E7%9A%84%E5%9B%B0%E6%93%BE%E3%80%82%0A%0A%20%20%20%20%20%20%20%20Keras%E9%80%8F%E9%81%8EImageDataGenerator%20class%E6%8F%90%E4%BE%9BData%20augmentation%E7%9B%B8%E9%97%9C%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%A6%82%EF%BC%9A%0A%0A%E8%B3%87%E6%96%99%E7%9A%84%E6%AD%A3%E8%A6%8F%E5%8C%96normalization%EF%BC%9A%E5%8F%AF%E9%87%9D%E5%B0%8DSample-wise%EF%BC%88%E6%AF%8F%E6%AC%A1%E5%8F%96%E6%A8%A3%E7%9A%84sample%20batch%EF%BC%89%E6%88%96Feature-wise%EF%BC%88%E6%95%B4%E9%AB%94%E7%9A%84dataset%EF%BC%89%0A%E8%B3%87%E6%96%99%E7%99%BD%E5%8C%96%EF%BC%88Whitening%EF%BC%89%E8%99%95%E7%90%86%EF%BC%9A%E6%8F%90%E4%BE%9BZCA%20Whitening%E8%99%95%E7%90%86%E3%80%82%EF%BC%88Whitening%E6%98%AF%E4%B8%80%E7%A8%AE%E5%B0%87%E8%B3%87%E6%96%99%E5%8E%BB%E5%86%97%E9%A4%98%E7%9A%84%E6%8A%80%E8%A1%93%EF%BC%89%0A%E5%BD%B1%E5%83%8F%E8%99%95%E7%90%86%EF%BC%9A%E7%BF%BB%E8%BD%89%E3%80%81%E6%97%8B%E8%BD%89%E3%80%81%E5%88%87%E8%A3%81%E3%80%81%E6%94%BE%E5%A4%A7%E7%B8%AE%E5%B0%8F%E3%80%81%E5%81%8F%E7%A7%BB%E2%80%A6%E7%AD%89%E3%80%82%0A%E6%9B%B4%E8%A9%B3%E7%B4%B0%E7%9A%84%E5%8F%83%E6%95%B8%E4%BD%BF%E7%94%A8%E8%AB%8B%E5%8F%83%E8%80%83https%3A%2F%2Fkeras.io%2Fpreprocessing%2Fimage%2F%E3%80%82%0A%0A%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8Data%20augmentation%0A%20%20%20%20%20%20%20%20%E5%9C%A8Keras%E4%BD%BF%E7%94%A8Data%20augmentation%E7%9A%84%E6%B5%81%E7%A8%8B%E6%98%AF%EF%BC%9A%0A%0A%E8%BC%89%E5%85%A5class%EF%BC%9A%0Afrom%20keras.preprocessing.image%20import%20ImageDataGenerator%0A%0A%E5%88%9D%E5%A7%8B%E5%8C%96ImageDataGenerator%E7%89%A9%E4%BB%B6%EF%BC%8C%E4%B8%A6%E5%AE%9A%E7%BE%A9%E5%85%B6%E5%8F%83%E6%95%B8%3A%0Adatagen%20%3D%20ImageDataGenerator(%0A%0A%20%20%20%20zca_whitening%3DFalse%2C%0A%0A%20%20%20%20rotation_range%3D40%2C%0A%0A%20%20%20%20width_shift_range%3D0.2%2C%0A%0A%20%20%20%20height_shift_range%3D0.2%2C%0A%0A%20%20%20%20shear_range%3D0.2%2C%0A%0A%20%20%20%20zoom_range%3D0.2%2C%0A%0A%20%20%20%20horizontal_flip%3DTrue%2C%0A%0A%20%20%20%20fill_mode%3D%E2%80%99nearest%E2%80%99)%0A%0A%E7%94%A2%E7%94%9F%E4%B8%8D%E5%90%8C%E7%9A%84%E5%9C%96%E5%BD%A2%EF%BC%8C%E4%BB%A5%E4%B8%8B%E5%88%86%E6%88%90%E5%85%A9%E7%A8%AE%E7%8B%80%E6%B3%81%E4%BE%86%E8%AA%AA%E6%98%8E%EF%BC%9A%0A%EF%BC%A1%EF%BC%89%E6%83%B3%E8%A6%81%E7%94%A2%E7%94%9F%E5%9C%96%E5%BD%A2%E6%AA%94%E5%88%B0disk%EF%BC%9A%0A%0A%E4%BE%8B%E5%A6%82%E8%A6%81%E5%BE%9E%E6%9F%90%E5%BC%B5%E7%9B%B8%E7%89%87%E7%94%A2%E7%94%9F10%E5%BC%B5%E6%AA%94%E5%90%8D%E9%96%8B%E9%A0%AD%E7%82%BAcat%E7%9A%84jpg%E5%9C%96%E7%89%87%EF%BC%8C%E4%B8%A6%E5%84%B2%E5%AD%98%E5%88%B0%E7%9B%AE%E9%8C%84preview%E4%B8%AD%EF%BC%9A%0Aimg%20%3D%20cv2.imread(%E2%80%9Ctest1.jpg%E2%80%9D)%0A%0Aimg%20%3D%20cv2.cvtColor(img%2C%20cv2.COLOR_BGR2RGB)%0A%0A%23%E6%A0%BC%E5%BC%8F%E5%BF%85%E9%A0%88%E7%82%BA%EF%BC%9A(sample%E6%95%B8%2C%20channels%2C%20height%2C%20width)%0A%0Aimg%20%3D%20img.reshape((1%2C)%20%2B%20img.shape)%0A%0Afor%20batch%20in%20datagen.flow(img%2C%20batch_size%3D10%2C%0A%0Asave_to_dir%3D%E2%80%99preview%E2%80%99%2C%20save_prefix%3D%E2%80%99cat%E2%80%99%2C%20save_format%3D%E2%80%99jpeg%E2%80%99)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%EF%BC%A2%EF%BC%89%E6%83%B3%E8%A6%81%E5%9C%A8%E8%A8%93%E7%B7%B4%E6%99%82%E9%82%8A%E7%94%A2%E7%94%9F%E5%9C%96%E5%BD%A2%EF%BC%9A%0A%0A%E9%80%99%E5%8F%88%E5%88%86%E5%85%A9%E7%A8%AE%E6%83%85%E6%B3%81%EF%BC%8C%E4%B8%80%E7%A8%AE%E6%98%AFdataset%E5%B7%B2%E8%BC%89%E5%85%A5memory%EF%BC%8C%E5%8F%A6%E4%B8%80%E7%A8%AE%E6%98%AFdataset%E6%94%BE%E5%9C%A8%E6%9F%90%E5%AF%A6%E9%AB%94%E7%9B%AE%E9%8C%84%E4%B8%AD%E5%B0%9A%E6%9C%AA%E8%AE%80%E5%85%A5%E3%80%82%0A%0Adataset%E5%B7%B2%E8%BC%89%E5%85%A5memory%EF%BC%9A%0Adatagen.fit(trainData)%0A%0Atrain_history%20%3D%20model.fit_generator(train_datagen.flow(trainData%2C%20%20%0A%0A%20%20%20%20%20%20trainLabels_hot%2C%20batch_size%3D64)%2C%0A%0A%20%20%20%20%20%20steps_per_epoch%3Dround(len(trainData)%2F64)%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20epochs%3D50%2C%20validation_data%3D(valiData%2C%20valiLabels_hot))%0A%0Adataset%E4%BD%8D%E5%9C%A8data%2Ftrain%E7%9B%AE%E9%8C%84%E4%B8%8B%EF%BC%9A%0AtrainData%20%3D%20train_datagen.flow_from_directory(%0A%0A%20%20%20%20%20%20%20%20%E2%80%9Cdata%2Ftrain%E2%80%9D%2C%0A%0A%20%20%20%20%20%20%20%20target_size%3D(150%2C%20150)%2C%20%20%23%E5%8F%AF%E4%BB%A5%E5%9C%A8%E6%AD%A4%E6%8C%87%E5%AE%9A%E8%A6%81rescale%E7%9A%84%E5%B0%BA%E5%AF%B8%0A%0A%20%20%20%20%20%20%20%20batch_size%3D64%2C%0A%0A%20%20%20%20%20%20%20%20class_mode%3D%E2%80%99binary%E2%80%99)%0A%0Amodel.fit_generator(%0A%0A%20%20%20%20%20%20%20%20trainData%2C%0A%0A%20%20%20%20%20%20%20%20steps_per_epoch%3D%20round(len(trainData)%2F64)%2C%0A%0A%20%20%20%20%20%20%20%20epochs%3D50%2C%0A%0Avalidation_data%3D(valiData%2C%20valiLabels_hot)%20)%0A%0AData%20augmentation%E7%9A%84%E6%95%88%E6%9E%9C%0A%E4%B8%8B%E6%96%B9%E7%AF%84%E4%BE%8B%E7%82%BA%E8%AE%80%E5%85%A5%E4%B8%80%E5%BC%B5%E5%9C%96%E7%89%87%EF%BC%8C%E7%84%B6%E5%BE%8C%E9%80%8F%E9%81%8EData%20augmentation%E4%BE%86%E7%94%A2%E7%94%9F%E4%B8%8D%E5%90%8C%E7%9A%84%E5%9C%96%E7%89%87%E7%82%BA%E4%BE%8B%EF%BC%8C%E6%82%A8%E5%8F%AF%E4%BB%A5%E5%90%8C%E6%AD%A5%E9%96%8B%E5%95%9Fhttps%3A%2F%2Fgithub.com%2Fch-tseng%2Fdata-augmentation-Keras%2Fblob%2Fmaster%2FDataAugmentation-1.ipynb%20%E4%BE%86%E6%AA%A2%E8%A6%96%E5%85%B6%E6%95%88%E6%9E%9C%0A%0A%E8%BC%89%E5%85%A5%E7%9B%B8%E9%97%9Cclass%E5%8F%8Amodule%0Aimport%20cv2%0A%0Afrom%20matplotlib%20import%20pyplot%20as%20plt%0A%0A%25matplotlib%20inline%0A%0Afrom%20pylab%20import%20rcParams%0A%0ArcParams%5B%E2%80%98figure.figsize%E2%80%99%5D%20%3D%2015%2C%2015%0A%0Afrom%20keras.preprocessing.image%20import%20ImageDataGenerator%2C%20array_to_img%2C%20img_to_array%2C%20load_img%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp.png%0A%0A%E6%8C%87%E5%AE%9A%E4%B8%80%E5%BC%B5%E7%9B%B8%E7%89%87%0AimgForTest%20%3D%20%E2%80%9C..%2Ftest1.jpg%22%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp0.png%0A%0A%E8%AE%80%E5%85%A5%E6%8C%87%E5%AE%9A%E7%9B%B8%E7%89%87%EF%BC%9A%0A%E4%BD%BF%E7%94%A8opencv%E8%AE%80%E5%85%A5%E5%9C%96%E7%89%87%EF%BC%8C%E7%94%B1%E6%96%BCopencv%E9%A0%90%E8%A8%AD%E6%A0%BC%E5%BC%8F%E7%82%BABGR%EF%BC%8C%E5%9B%A0%E6%AD%A4%E9%9C%80%E7%94%A8cvtColor%E8%BD%89%E7%82%BARGB%E6%A0%BC%E5%BC%8F%E3%80%82%0A%0Aimg%20%3D%20cv2.imread(imgForTest)%0A%0Aimg%20%3D%20cv2.cvtColor(img%2C%20cv2.COLOR_BGR2RGB)%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp3.png%0A%0A%E9%A1%AF%E7%A4%BA%E5%9C%96%E7%89%87%E5%8F%8A%E5%85%B6%E8%B3%87%E6%96%99%E7%B6%AD%E5%BA%A6%EF%BC%9A%0A%E7%94%B1%E6%96%BC%E6%88%91%E5%80%91%E6%98%AFload%E5%96%AE%E5%BC%B5%E5%9C%96%E7%89%87%E8%80%8C%E9%9D%9Earray%EF%BC%8C%E5%9B%A0%E6%AD%A4%E9%9C%80%E8%A6%81%E4%BF%AE%E6%94%B9%E5%85%B6dimention%EF%BC%8C%E5%9C%A8%E5%89%8D%E6%96%B9%E5%8A%A0%E5%85%A5ID%E9%A0%85%E6%AC%A1%E3%80%82%0A%0Aplt.imshow(img)%0A%0Aprint(img.shape)%0A%0Aimg%20%3D%20img.reshape((1%2C)%20%2B%20img.shape)%0A%0Aprint(img.shape)%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp7.png%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp8.png%0A%0A%E5%AE%9A%E7%BE%A9%E7%9B%B8%E9%97%9C%E5%8F%83%E6%95%B8%EF%BC%9A%0A%E6%82%A8%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E4%B8%8B%E6%96%B9%E7%9A%84ImageDataGenerator%E5%8F%83%E6%95%B8%E5%80%BC%E6%9C%89rotation%E3%80%81shift%E3%80%81shear%E3%80%81flip%E3%80%81zoom%E3%80%81fill_mode%E2%80%A6%E7%AD%89%EF%BC%8C%E5%BE%9E%E5%AD%97%E7%BE%A9%E4%B8%8A%E5%8D%B3%E5%8F%AF%E7%9E%AD%E8%A7%A3%E5%85%B6%E5%9C%96%E5%BD%A2%E6%95%88%E6%9E%9C%EF%BC%8C%E7%9B%B8%E9%97%9C%E8%A9%B3%E7%B4%B0%E5%8F%83%E6%95%B8%E8%AA%AA%E6%98%8E%E8%AB%8B%E5%8F%83%E8%80%83%EF%BC%9Ahttps%3A%2F%2Fkeras.io%2Fpreprocessing%2Fimage%2F%0A%0Adatagen%20%3D%20ImageDataGenerator(%20%20%20%20%0A%0A%20%20%20%20rotation_range%3D40%2C%0A%0A%20%20%20%20width_shift_range%3D0.2%2C%0A%0A%20%20%20%20height_shift_range%3D0.2%2C%0A%0A%20%20%20%20shear_range%3D0.2%2C%0A%0A%20%20%20%20zoom_range%3D0.2%2C%0A%0A%20%20%20%20horizontal_flip%3DTrue%2C%0A%0A%20%20%20%20fill_mode%3D%E2%80%99nearest%E2%80%99)%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp9.png%0A%0A%E7%B6%93%E7%94%B1augmentation%E7%94%A2%E7%94%9F%E5%90%84%E7%A8%AE%E5%9C%96%E5%BD%A2%EF%BC%9A%0Adatagen.flow%E6%9C%83%E4%BE%9D%E6%93%9A%E6%8C%87%E5%AE%9A%E5%8F%83%E6%95%B8%E7%94%A2%E7%94%9F%E5%90%84%E5%BC%8F%E5%9C%96%E5%BD%A2%EF%BC%8C%E6%82%A8%E5%8F%AF%E4%BB%A5%E8%BC%B8%E5%85%A5%E4%B8%80%E5%80%8B%E5%9C%96%E5%BD%A2%E9%99%A3%E5%88%97%E6%88%96%E6%9C%AC%E7%AF%84%E4%BE%8B%E4%B8%80%E6%A8%A3%E7%9A%84%E5%96%AE%E5%BC%B5%E5%9C%96%E7%89%87%E3%80%82%0A%0Ai%20%3D%200%0A%0Afor%20batch%20in%20datagen.flow(img%2C%20batch_size%3D10%2C%0A%0A%20%20%20%20%20%20%20%20%20%20save_to_dir%3D%E2%80%99small-2000%2Fpreview%E2%80%99%2C%20save_prefix%3D%E2%80%99cat%E2%80%99%2C%20save_format%3D%E2%80%99jpeg%E2%80%99)%3A%0A%0A%20%20%20%20plt.subplot(5%2C4%2C1%20%2B%20i)%0A%0A%20%20%20%20plt.axis(%E2%80%9Coff%22)%0A%0A%20%20%20%0A%0A%20%20%20%20augImage%20%3D%20batch%5B0%5D%0A%0A%20%20%20%20augImage%20%3D%20augImage.astype(%E2%80%98float32%E2%80%99)%0A%0A%20%20%20%20augImage%20%2F%3D%20255%0A%0A%20%20%20%20plt.imshow(augImage)%0A%0A%20%20%20%0A%0A%20%20%20%20i%20%2B%3D%201%0A%0A%20%20%20%20if%20i%20%3E%2019%3A%0A%0A%20%20%20%20%20%20%20%20break%0A%0AC%3A%5CUsers%5CCHE7C6~1.TSE%5CAppData%5CLocal%5CTemp%5Cx10sctmp10.png%0A%0A%0A%0A%E5%90%8C%E6%A8%A3%E7%9A%84%EF%BC%8C%E4%B8%80%E5%BC%B5%E5%B0%8F%E7%8B%97%E7%9A%84%E7%85%A7%E7%89%87%E5%8F%AF%E4%BB%A5%E7%94%A2%E7%94%9F%E9%80%99%E9%BA%BC%E5%A4%9A%E7%9A%84%E6%96%B0%E5%9C%96%E7%89%87%EF%BC%9Ahttps%3A%2F%2Fgithub.com%2Fch-tseng%2Fdata-augmentation-Keras%2Fblob%2Fmaster%2Fdogcat-augmentation.ipynb%0A%0A%0A%0Amodel.fit%E8%88%87model.fit_generator%0A%20%20%20%20%20%20%20%20%E6%B3%A8%E6%84%8F%E5%9C%A8%E4%BD%BF%E7%94%A8Data%20augmentation%E6%99%82%EF%BC%8C%E9%80%B2%E8%A1%8C%E8%A8%93%E7%B7%B4%E6%89%80%E4%BD%BF%E7%94%A8%E7%9A%84model.fit%E9%A0%88%E6%94%B9%E7%82%BAmodel.fit_generator%E6%89%8D%E8%AE%93%E7%B3%BB%E7%B5%B1on-fly%E7%9A%84%E7%94%A2%E7%94%9F%E6%96%B0%E5%9C%96%E5%83%8F%E6%8F%90%E4%BE%9B%E8%A8%93%E7%B7%B4%E4%BD%BF%E7%94%A8%E3%80%82model.fit%E8%88%87model.fit_generator%E9%80%99%E5%85%A9%E5%80%8B%E6%8C%87%E4%BB%A4%E9%83%BD%E6%98%AFfor%E7%9B%B8%E5%90%8C%E7%9A%84%E8%A8%93%E7%B7%B4%E7%94%A8%E9%80%94%EF%BC%8C%E4%BD%86%E4%BD%BF%E7%94%A8%E6%99%82%E6%A9%9F%E5%A4%A7%E6%9C%89%E4%B8%8D%E5%90%8C%EF%BC%9A%0A%0Amodel.fit%20%E9%81%A9%E7%94%A8%E6%96%BCDataset%E5%B7%B2ready%EF%BC%8C%E4%B8%8D%E9%9C%80%E5%86%8D%E9%80%B2%E8%A1%8C%E4%BB%BB%E4%BD%95%E9%A0%90%E8%99%95%E7%90%86%E5%8F%AF%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%E3%80%82%0Amodel.fit_generator%20%E9%81%A9%E7%94%A8%E6%96%BCDataset%E5%B0%9A%E6%9C%AAready%EF%BC%8C%E9%9C%80%E8%A6%81%E5%9C%A8%E6%AF%8F%E6%89%B9%E6%AC%A1%E8%A8%93%E7%B7%B4%E5%85%88%E9%80%B2%E8%A1%8C%E9%A0%90%E8%99%95%E7%90%86%EF%BC%88%E6%88%96%E7%94%A2%E7%94%9F%EF%BC%89%E3%80%82%0A%E7%94%B1%E6%96%BCmodel.fit_generator%E5%9C%A8%E6%AF%8F%E6%89%B9%E6%AC%A1%E8%A8%93%E7%B7%B4%E5%89%8D%E6%89%8Don%20demand%E6%88%96on-the-fly%E8%99%95%E7%90%86%E6%88%96%E7%94%A2%E7%94%9Fdata%EF%BC%8C%E5%9B%A0%E6%AD%A4%E8%83%BD%E6%AF%94%E8%BC%83%E6%9C%89%E6%95%88%E7%8E%87%E7%9A%84%E6%87%89%E7%94%A8%E5%9C%A8%E4%B8%80%E4%BA%9B%E7%A1%AC%E9%AB%94%E8%B3%87%E6%BA%90%E4%B8%8D%E5%A4%AA%E8%B6%B3%E5%A4%A0%E7%9A%84%E6%A9%9F%E5%99%A8%E4%B8%8A%EF%BC%88%E4%BE%8B%E5%A6%82RAM%E5%83%85%E6%9C%898G%E7%84%B6%E8%80%8Cdataset%E5%8D%BB%E6%9C%891TB%E7%9A%84%E6%83%85%E6%B3%81%EF%BC%89%EF%BC%8Cmodel.fit_generator%E5%8F%AF%E9%81%BF%E5%85%8Dload%E6%95%B4%E5%80%8Bdataset%EF%BC%8C%E5%8F%AA%E9%9C%80%E8%A6%81%E5%9C%A8%E6%AF%8F%E6%89%B9%E6%AC%A1%E8%A8%93%E7%B7%B4%E5%89%8Don-demand%E7%94%A2%E7%94%9F%E9%9C%80%E8%A6%81%E6%95%B8%E9%87%8F%E7%9A%84data%E3%80%82%0A%0A%E9%82%A3%E9%BA%BC%EF%BC%8C%E6%88%91%E5%80%91%E8%A6%81%E5%A6%82%E4%BD%95%E5%AE%9A%E7%BE%A9%E8%A6%81%E7%B6%93%E7%94%B1Data%20augmentation%E7%94%A2%E7%94%9F%E5%A4%9A%E5%B0%91%E8%B3%87%E6%96%99%E5%91%A2%EF%BC%9F%E6%9C%80%E7%B0%A1%E5%96%AE%E7%9A%84%E6%96%B9%E5%BC%8F%E6%98%AF%E9%80%8F%E9%81%8E%E5%8F%83%E6%95%B8samples_per_epoch%EF%BC%8C%E8%A9%B2%E5%8F%83%E6%95%B8%E5%AE%9A%E7%BE%A9%E6%AF%8F%E6%AC%A1epoch%E8%A6%81%E7%94%A2%E7%94%9F%E5%A4%9A%E5%B0%91sample%20data%EF%BC%88%E4%BA%A6%E5%8D%B3%E7%B3%BB%E7%B5%B1%E5%9C%A8%E6%AF%8F%E5%80%8Bepoch%E6%89%80%E8%83%BD%E7%9C%8B%E5%88%B0%E7%9A%84%E8%B3%87%E6%96%99%E6%95%B8%E9%87%8F%EF%BC%89%E3%80%82%E5%9C%A8%E4%B8%8B%E6%96%B9%E7%9A%84%E4%BE%8B%E5%AD%90%E4%B8%AD%EF%BC%8C%E6%88%91%E5%80%91%E8%A8%AD%E5%AE%9A%E7%82%BAtraining%20dataset%E7%9A%84%EF%BC%92%E5%80%8D%E6%95%B8%E9%87%8F%E3%80%82%0A%0Aepochs%20%3D%2015%0A%0Abatch_size%20%3D%2032%0A%0Atrain_history%20%3D%20model.fit_generator(%0A%0Atrain_datagen.flow(trainData_normalize%2C%20trainLabels_hot%2C%20batch_size%3Dbatch_size)%2C%0A%0Asamples_per_epoch%3D(len(trainData)*2)%2C%20nb_epoch%3Depochs%2C%0A%0Avalidation_data%3D(valiData_normalize%2C%20valiLabels_hot))” message=”” highlight=”” provider=”manual”/]如此一來,如果我們的dataset只有1,000張,但透過augmentation實際上訓練的數量可擴增到2,000張,是不是很方便呢?
我們也可以用另一種方式,不先給予total的training數目而是指定每個epoch要分成幾個batch來run(參數steps_per_epoch),以及每次batch所要提取的sample數目為多少?(參數batch size),因此,一個epoch所train的dataset數目就是steps_per_epoch乘上batch_size。下面的例子同樣每epoch會run 2倍於目前的dataset數量。(注意:nb_epoch 參數自Keras 2.0開始已被epoch參數取代)
[pastacode lang=”markup” manual=”%20%20%20%20%20%20%20%20epochs%20%3D%2050%0A%0Abatch_size%20%3D%2032%0A%0Asteps_per_epoch%3Dint((len(trainData)*2)%2Fbatch_size)%0A%0Atrain_history%20%3D%20model.fit_generator(%0A%0Atrain_datagen.flow(trainData_normalize%2C%20trainLabels_hot%2C%20atch_size%3Dbatch_size)%2C%0A%0Asteps_per_epoch%3Dsteps_per_epoch%2C%20epochs%3Depochs%2C%0A%0Avalidation_data%3D(valiData_normalize%2C%20valiLabels_hot))” message=”” highlight=”” provider=”manual”/]實際應用
接下來我以之前作過的「使用CNN 識別辦公區狀態」為例子,該dataset的資訊如下:
- 格式:jpeg,224×224 pixels
- 相片日期:2017/04~2017/09
- 分類:共有17種categories,每個category有70張相片,共1,190張。
每張圖片依如下分為四個區域並給予label:由左上角本人座位開始順時間方向,1代表有人,0代表無人,亦即該區只要有人出現該區便視為1,因此,下面的兩張圖皆會被label為1-1-0-1。
![]() |
![]() |
若剛好有人橫跨兩個區域,則視其在那一區域佔的比例較多來決定,例如:
- Review並重新組合或調整model架構。
- 將資料進行正規化,如L1/L2 regularization。
- 使用dropout技術。
- 使用Data augmentation(資料增強)技術。
dropout技術在之前已介紹並實際應用過,在此所要介紹的是Data augmentation。不同於Dropout透過丟棄一定比例的神經元以模擬不同的dataset,Data augmentation則是從既有的dataset中產生出更多的資料讓系統去學習,說坦白一點,是創造更多的「假」資料,來彌補我們資料不足的缺憾。
雖然是假的資料,但也是從原始資料內容修改產生的,因此Data augmentation經過證實的確可解決資料不足的困境並提昇系統訓練的準確率哦!我們來看看要怎麼使用它。
Data augmentation原理
一張圖片經過旋轉、調整大小、比例尺寸,或者改變亮度色溫、翻轉等處理後,我們人眼仍能辨識出來是相同的相片,但是對機器來說那可是完全不同的新圖像了,因此, Data augmentation就是將dataset中既有的圖片予以修改變形,以創造出更多的圖片來讓機器學習,彌補資料量不足的困擾。
Keras透過ImageDataGenerator class提供Data augmentation相關的功能,如:
- 資料的正規化normalization:可針對Sample-wise(每次取樣的sample batch)或Feature-wise(整體的dataset)
- 資料白化(Whitening)處理:提供ZCA Whitening處理。(Whitening是一種將資料去冗餘的技術)
- 影像處理:翻轉、旋轉、切裁、放大縮小、偏移…等。
更詳細的參數使用請參考https://keras.io/preprocessing/image/。
如何使用Data augmentation
在Keras使用Data augmentation的流程是:
- 載入class:
from keras.preprocessing.image import ImageDataGenerator
- 初始化ImageDataGenerator物件,並定義其參數:
datagen = ImageDataGenerator(
zca_whitening=False,
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’)
- 產生不同的圖形,以下分成兩種狀況來說明:
A)想要產生圖形檔到disk:
- 例如要從某張相片產生10張檔名開頭為cat的jpg圖片,並儲存到目錄preview中:
img = cv2.imread(“test1.jpg”)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#格式必須為:(sample數, channels, height, width)
img = img.reshape((1,) + img.shape)
for batch in datagen.flow(img, batch_size=10,
save_to_dir=’preview’, save_prefix=’cat’, save_format=’jpeg’)
B)想要在訓練時邊產生圖形:
這又分兩種情況,一種是dataset已載入memory,另一種是dataset放在某實體目錄中尚未讀入。
- dataset已載入memory:
datagen.fit(trainData)
train_history = model.fit_generator(train_datagen.flow(trainData,
trainLabels_hot, batch_size=64),
steps_per_epoch=round(len(trainData)/64),
epochs=50, validation_data=(valiData, valiLabels_hot))
- dataset位在data/train目錄下:
trainData = train_datagen.flow_from_directory(
“data/train”,
target_size=(150, 150), #可以在此指定要rescale的尺寸
batch_size=64,
class_mode=’binary’)
model.fit_generator(
trainData,
steps_per_epoch= round(len(trainData)/64),
epochs=50,
validation_data=(valiData, valiLabels_hot) )
Data augmentation的效果
下方範例為讀入一張圖片,然後透過Data augmentation來產生不同的圖片為例,您可以同步開啟https://github.com/ch-tseng/data-augmentation-Keras/blob/master/DataAugmentation-1.ipynb 來檢視其效果
- 載入相關class及module
import cv2
from matplotlib import pyplot as plt
%matplotlib inline
from pylab import rcParams
rcParams[‘figure.figsize’] = 15, 15
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img

- 指定一張相片
imgForTest = “../test1.jpg”
![]()
- 讀入指定相片:
使用opencv讀入圖片,由於opencv預設格式為BGR,因此需用cvtColor轉為RGB格式。
img = cv2.imread(imgForTest)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
![]()
- 顯示圖片及其資料維度:
由於我們是load單張圖片而非array,因此需要修改其dimention,在前方加入ID項次。
plt.imshow(img)
print(img.shape)
img = img.reshape((1,) + img.shape)
print(img.shape)


- 定義相關參數:
您可以看到下方的ImageDataGenerator參數值有rotation、shift、shear、flip、zoom、fill_mode…等,從字義上即可瞭解其圖形效果,相關詳細參數說明請參考:https://keras.io/preprocessing/image/
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’)

- 經由augmentation產生各種圖形:
datagen.flow會依據指定參數產生各式圖形,您可以輸入一個圖形陣列或本範例一樣的單張圖片。
i = 0
for batch in datagen.flow(img, batch_size=10,
save_to_dir=’small-2000/preview’, save_prefix=’cat’, save_format=’jpeg’):
plt.subplot(5,4,1 + i)
plt.axis(“off”)
augImage = batch[0]
augImage = augImage.astype(‘float32’)
augImage /= 255
plt.imshow(augImage)
i += 1
if i > 19:
break


同樣的,一張小狗的照片可以產生這麼多的新圖片:https://github.com/ch-tseng/data-augmentation-Keras/blob/master/dogcat-augmentation.ipynb

model.fit與model.fit_generator
注意在使用Data augmentation時,進行訓練所使用的model.fit須改為model.fit_generator才讓系統on-fly的產生新圖像提供訓練使用。model.fit與model.fit_generator這兩個指令都是for相同的訓練用途,但使用時機大有不同:
- model.fit 適用於Dataset已ready,不需再進行任何預處理可直接使用。
- model.fit_generator 適用於Dataset尚未ready,需要在每批次訓練先進行預處理(或產生)。
由於model.fit_generator在每批次訓練前才on demand或on-the-fly處理或產生data,因此能比較有效率的應用在一些硬體資源不太足夠的機器上(例如RAM僅有8G然而dataset卻有1TB的情況),model.fit_generator可避免load整個dataset,只需要在每批次訓練前on-demand產生需要數量的data。
那麼,我們要如何定義要經由Data augmentation產生多少資料呢?最簡單的方式是透過參數samples_per_epoch,該參數定義每次epoch要產生多少sample data(亦即系統在每個epoch所能看到的資料數量)。在下方的例子中,我們設定為training dataset的2倍數量。
epochs = 15
batch_size = 32
train_history = model.fit_generator(
train_datagen.flow(trainData_normalize, trainLabels_hot, batch_size=batch_size),
samples_per_epoch=(len(trainData)*2), nb_epoch=epochs,
validation_data=(valiData_normalize, valiLabels_hot))
如此一來,如果我們的dataset只有1,000張,但透過augmentation實際上訓練的數量可擴增到2,000張,是不是很方便呢?
我們也可以用另一種方式,不先給予total的training數目而是指定每個epoch要分成幾個batch來run(參數steps_per_epoch),以及每次batch所要提取的sample數目為多少?(參數batch size),因此,一個epoch所train的dataset數目就是steps_per_epoch乘上batch_size。下面的例子同樣每epoch會run 2倍於目前的dataset數量。(注意:nb_epoch 參數自Keras 2.0開始已被epoch參數取代)
epochs = 50
batch_size = 32
steps_per_epoch=int((len(trainData)*2)/batch_size)
train_history = model.fit_generator(
train_datagen.flow(trainData_normalize, trainLabels_hot, atch_size=batch_size),
steps_per_epoch=steps_per_epoch, epochs=epochs,
validation_data=(valiData_normalize, valiLabels_hot))
實際應用
接下來我以之前作過的「使用CNN 識別辦公區狀態」為例子,該dataset的資訊如下:
- 格式:jpeg,224×224 pixels
- 相片日期:2017/04~2017/09
- 分類:共有17種categories,每個category有70張相片,共1,190張。
每張圖片依如下分為四個區域並給予label:由左上角本人座位開始順時間方向,1代表有人,0代表無人,亦即該區只要有人出現該區便視為1,因此,下面的兩張圖皆會被label為1-1-0-1。
![]() |
![]() |
若剛好有人橫跨兩個區域,則視其在那一區域佔的比例較多來決定,例如:


總計會有17種情況,因此所有相片會被歸屬於17個不同的labels(Categories)。每個category舉例一張如下(後方的藍色數字代表其label的代碼):
| 0-0-0-0(11) | 1-0-0-0(7) | 0-1-0-0(14) |
![]() |
![]() |
![]() |
| 0-0-1-0(9) | 0-0-0-1(12) | 1-1-0-0(6) |
![]() |
![]() |
![]() |
| 0-1-1-0(16) | 0-0-1-1(1) | 1-0-1-0(8) |
![]() |
![]() |
![]() |
| 0-1-0-1(2) | 1-0-0-1(4) | 1-1-1-0(13) |
![]() |
![]() |
![]() |
| 0-1-1-1(3) | 1-0-1-1(0) | 1-1-0-1(15) |
![]() |
![]() |
![]() |
| 1-1-1-1(10) | Dark(5) | |
![]() |
![]() |
- Review並重新組合或調整model架構。
- 將資料進行正規化,如L1/L2 regularization。
- 使用dropout技術。
- 使用Data augmentation(資料增強)技術。
dropout技術在之前已介紹並實際應用過,在此所要介紹的是Data augmentation。不同於Dropout透過丟棄一定比例的神經元以模擬不同的dataset,Data augmentation則是從既有的dataset中產生出更多的資料讓系統去學習,說坦白一點,是創造更多的「假」資料,來彌補我們資料不足的缺憾。
雖然是假的資料,但也是從原始資料內容修改產生的,因此Data augmentation經過證實的確可解決資料不足的困境並提昇系統訓練的準確率哦!我們來看看要怎麼使用它。
Data augmentation原理
一張圖片經過旋轉、調整大小、比例尺寸,或者改變亮度色溫、翻轉等處理後,我們人眼仍能辨識出來是相同的相片,但是對機器來說那可是完全不同的新圖像了,因此, Data augmentation就是將dataset中既有的圖片予以修改變形,以創造出更多的圖片來讓機器學習,彌補資料量不足的困擾。
Keras透過ImageDataGenerator class提供Data augmentation相關的功能,如:
- 資料的正規化normalization:可針對Sample-wise(每次取樣的sample batch)或Feature-wise(整體的dataset)
- 資料白化(Whitening)處理:提供ZCA Whitening處理。(Whitening是一種將資料去冗餘的技術)
- 影像處理:翻轉、旋轉、切裁、放大縮小、偏移…等。
更詳細的參數使用請參考https://keras.io/preprocessing/image/。
如何使用Data augmentation
在Keras使用Data augmentation的流程是:
- 載入class:
from keras.preprocessing.image import ImageDataGenerator
- 初始化ImageDataGenerator物件,並定義其參數:
datagen = ImageDataGenerator(
zca_whitening=False,
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’)
- 產生不同的圖形,以下分成兩種狀況來說明:
A)想要產生圖形檔到disk:
- 例如要從某張相片產生10張檔名開頭為cat的jpg圖片,並儲存到目錄preview中:
img = cv2.imread(“test1.jpg”)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#格式必須為:(sample數, channels, height, width)
img = img.reshape((1,) + img.shape)
for batch in datagen.flow(img, batch_size=10,
save_to_dir=’preview’, save_prefix=’cat’, save_format=’jpeg’)
B)想要在訓練時邊產生圖形:
這又分兩種情況,一種是dataset已載入memory,另一種是dataset放在某實體目錄中尚未讀入。
- dataset已載入memory:
datagen.fit(trainData)
train_history = model.fit_generator(train_datagen.flow(trainData,
trainLabels_hot, batch_size=64),
steps_per_epoch=round(len(trainData)/64),
epochs=50, validation_data=(valiData, valiLabels_hot))
- dataset位在data/train目錄下:
trainData = train_datagen.flow_from_directory(
“data/train”,
target_size=(150, 150), #可以在此指定要rescale的尺寸
batch_size=64,
class_mode=’binary’)
model.fit_generator(
trainData,
steps_per_epoch= round(len(trainData)/64),
epochs=50,
validation_data=(valiData, valiLabels_hot) )
Data augmentation的效果
下方範例為讀入一張圖片,然後透過Data augmentation來產生不同的圖片為例,您可以同步開啟https://github.com/ch-tseng/data-augmentation-Keras/blob/master/DataAugmentation-1.ipynb 來檢視其效果
- 載入相關class及module
import cv2
from matplotlib import pyplot as plt
%matplotlib inline
from pylab import rcParams
rcParams[‘figure.figsize’] = 15, 15
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img

- 指定一張相片
imgForTest = “../test1.jpg”
![]()
- 讀入指定相片:
使用opencv讀入圖片,由於opencv預設格式為BGR,因此需用cvtColor轉為RGB格式。
img = cv2.imread(imgForTest)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
![]()
- 顯示圖片及其資料維度:
由於我們是load單張圖片而非array,因此需要修改其dimention,在前方加入ID項次。
plt.imshow(img)
print(img.shape)
img = img.reshape((1,) + img.shape)
print(img.shape)


- 定義相關參數:
您可以看到下方的ImageDataGenerator參數值有rotation、shift、shear、flip、zoom、fill_mode…等,從字義上即可瞭解其圖形效果,相關詳細參數說明請參考:https://keras.io/preprocessing/image/
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’)

- 經由augmentation產生各種圖形:
datagen.flow會依據指定參數產生各式圖形,您可以輸入一個圖形陣列或本範例一樣的單張圖片。
i = 0
for batch in datagen.flow(img, batch_size=10,
save_to_dir=’small-2000/preview’, save_prefix=’cat’, save_format=’jpeg’):
plt.subplot(5,4,1 + i)
plt.axis(“off”)
augImage = batch[0]
augImage = augImage.astype(‘float32’)
augImage /= 255
plt.imshow(augImage)
i += 1
if i > 19:
break


同樣的,一張小狗的照片可以產生這麼多的新圖片:https://github.com/ch-tseng/data-augmentation-Keras/blob/master/dogcat-augmentation.ipynb

model.fit與model.fit_generator
注意在使用Data augmentation時,進行訓練所使用的model.fit須改為model.fit_generator才讓系統on-fly的產生新圖像提供訓練使用。model.fit與model.fit_generator這兩個指令都是for相同的訓練用途,但使用時機大有不同:
- model.fit 適用於Dataset已ready,不需再進行任何預處理可直接使用。
- model.fit_generator 適用於Dataset尚未ready,需要在每批次訓練先進行預處理(或產生)。
由於model.fit_generator在每批次訓練前才on demand或on-the-fly處理或產生data,因此能比較有效率的應用在一些硬體資源不太足夠的機器上(例如RAM僅有8G然而dataset卻有1TB的情況),model.fit_generator可避免load整個dataset,只需要在每批次訓練前on-demand產生需要數量的data。
那麼,我們要如何定義要經由Data augmentation產生多少資料呢?最簡單的方式是透過參數samples_per_epoch,該參數定義每次epoch要產生多少sample data(亦即系統在每個epoch所能看到的資料數量)。在下方的例子中,我們設定為training dataset的2倍數量。
epochs = 15
batch_size = 32
train_history = model.fit_generator(
train_datagen.flow(trainData_normalize, trainLabels_hot, batch_size=batch_size),
samples_per_epoch=(len(trainData)*2), nb_epoch=epochs,
validation_data=(valiData_normalize, valiLabels_hot))
如此一來,如果我們的dataset只有1,000張,但透過augmentation實際上訓練的數量可擴增到2,000張,是不是很方便呢?
我們也可以用另一種方式,不先給予total的training數目而是指定每個epoch要分成幾個batch來run(參數steps_per_epoch),以及每次batch所要提取的sample數目為多少?(參數batch size),因此,一個epoch所train的dataset數目就是steps_per_epoch乘上batch_size。下面的例子同樣每epoch會run 2倍於目前的dataset數量。(注意:nb_epoch 參數自Keras 2.0開始已被epoch參數取代)
epochs = 50
batch_size = 32
steps_per_epoch=int((len(trainData)*2)/batch_size)
train_history = model.fit_generator(
train_datagen.flow(trainData_normalize, trainLabels_hot, atch_size=batch_size),
steps_per_epoch=steps_per_epoch, epochs=epochs,
validation_data=(valiData_normalize, valiLabels_hot))
實際應用
接下來我以之前作過的「使用CNN 識別辦公區狀態」為例子,該dataset的資訊如下:
- 格式:jpeg,224×224 pixels
- 相片日期:2017/04~2017/09
- 分類:共有17種categories,每個category有70張相片,共1,190張。
每張圖片依如下分為四個區域並給予label:由左上角本人座位開始順時間方向,1代表有人,0代表無人,亦即該區只要有人出現該區便視為1,因此,下面的兩張圖皆會被label為1-1-0-1。
![]() |
![]() |
若剛好有人橫跨兩個區域,則視其在那一區域佔的比例較多來決定,例如:


總計會有17種情況,因此所有相片會被歸屬於17個不同的labels(Categories)。每個category舉例一張如下(後方的藍色數字代表其label的代碼):
| 0-0-0-0(11) | 1-0-0-0(7) | 0-1-0-0(14) |
![]() |
![]() |
![]() |
| 0-0-1-0(9) | 0-0-0-1(12) | 1-1-0-0(6) |
![]() |
![]() |
![]() |
| 0-1-1-0(16) | 0-0-1-1(1) | 1-0-1-0(8) |
![]() |
![]() |
![]() |
| 0-1-0-1(2) | 1-0-0-1(4) | 1-1-1-0(13) |
![]() |
![]() |
![]() |
| 0-1-1-1(3) | 1-0-1-1(0) | 1-1-0-1(15) |
![]() |
![]() |
![]() |
| 1-1-1-1(10) | Dark(5) | |
![]() |
![]() |
比較有否使用Data Augmentation的差異
未使用Data Augmentation
由於此dataset總圖片張數僅有1,190張,因此我們打算比較看看加入Data Augmentation功能是否能提昇其準確率。因為時間因素,我們僅訓練15 epoches,首先,是未使用data augmentation的結果:

F1-score成績僅為0.69。
使用Data Augmentation
接下來我們看看加入data augmentation的效果。在下方,我們增加一個調整曝光值的function,讓data augmentation能產生各種不同亮度的相片作為新圖片來使用。
[pastacode lang=”markup” manual=”from%20skimage%20import%20exposure%0A%0Adef%20AHE(img)%3A%0A%0A%20%20%20%20img_adapteq%20%3D%20exposure.equalize_adapthist(img%2C%20clip_limit%3D0.03)%0A%0A%20%20%20%20return%20img_adapteq%0A%0Aif(dataAugment)%3A%0A%0A%20%20%20%20train_datagen%20%3D%20ImageDataGenerator(%0A%0A%20%20%20%20%20%20%20%20preprocessing_function%3DAHE%2C%0A%0A%20%20%20%20%20%20%20%20fill_mode%3D%E2%80%99nearest%E2%80%99)%0A%0A%20%20%20%0A%0A%20%20%20%20train_datagen.fit(trainData_normalize)” message=”” highlight=”” provider=”manual”/]
使用Test dataset測試結果,F1-score成績為0.85,發現使用Data augmentation讓成績大幅提昇了23%。
註:上述的程式碼已上傳Github,您可參考下方的連結:
1. 未使用Data augmentation的程式: https://github.com/ch-tseng/data-augmentation-Keras/blob/master/CNN-Meetingroom-Augmentation-No.ipynb
2. 使用Data augmentation的程式: https://github.com/ch-tseng/data-augmentation-Keras/blob/master/CNN-Meetingroom-Augmentation-2.ipynb
想了解更多CH.Tseng,可以點此連結 瀏覽更多文章喔~



















































