โมเดล Deep Neural Network มักจะมีปัญหา Overfit เมื่อเทรนกับ Dataset ที่มีขนาดเล็ก แต่เราสามารถแก้ปัญหา Overfit โดยใช้วิธีการ Ensembles คือ สร้างหลาย ๆ โมเดลแล้วเอา Output มาเฉลี่ยกัน แต่ทำแบบนี้ทั้งสิ้นเปลืองทรัพยากร เวลา และต้องคอย Maintain หลายโมเดลอีก เราจะมีวิธีอะไรที่ดีกว่านี้ไหม

Dropout Gif Animation. Credit: https://towardsdatascience.com/preventing-deep-neural-network-from-overfitting-953458db800a
Dropout Gif Animation. Credit: https://towardsdatascience.com/preventing-deep-neural-network-from-overfitting-953458db800a

Dropout

เราสามารถใช้แค่โมเดลเดียว มาจำลองเป็นหลาย ๆ โมเดลได้ โดยการสุ่มถอดบาง Node ออก ในระหว่างการเทรน วิธีนี้เรียกว่า Dropout เป็นวิธีที่ชาญฉลาด ประหยัดทั้งเวลา และทรัพยากร และที่สำคัญเราไม่ต้อง Maintain หลาย ๆ โมเดล

Dropout ถือเป็นวิธี Regularization แบบหนึ่ง ช่วยลดการจำข้อสอบ ลด Overfit และทำให้โมเดล Deep Neural Network ทุก ๆ สถาปัตยกรรม Generalization ดีขึ้น

Test error for different architectures with and without dropout. The networks have 2 to 4 hidden layers each with 1024 to 2048 units. Credit: http://jmlr.org/papers/v15/srivastava14a.html
Test error for different architectures with and without dropout. The networks have 2 to 4 hidden layers each with 1024 to 2048 units. Credit: http://jmlr.org/papers/v15/srivastava14a.html

เรามาเริ่มกันเลย

Open In Colab

0. Magic Commands

In [1]:
%reload_ext autoreload
%autoreload 2
%matplotlib inline

1. Import Library

In [2]:
from fastai import *
from fastai.vision import *
from fastai.metrics import accuracy

2. ข้อมูล

ใช้ชุดข้อมูล Dataset พันธุ์หมาแมว Oxford-IIIT Pet Dataset by O. M. Parkhi et al., 2012

In [3]:
path = untar_data(URLs.PETS)
path_images = path/'images'
filenames = get_image_files(path_images)

3. เตรียมข้อมูล

เพื่อความสะดวก เราจะประกาศฟังก์ชัน แล้วไปเรียกสร้างก่อน fit ด้วย Dropout แต่ละแบบ

เราจะไม่ทำ Data Augmentation จะได้เปรียบเทียบให้เห็นได้ชัด ๆ

In [4]:
batchsize = 32
epoch = 8
lr = slice(3e-6, 1e-2)
np.random.seed(55)
regex_pattern = r'/([^/]+)_\d+.jpg$'
transform = zoom_crop(scale=(1.0,1.0), do_rand=False)

def get_databunch():
    return ImageDataBunch.from_name_re(path_images, filenames, 
                                   regex_pattern, ds_tfms=transform, 
                                   size=224, bs=batchsize).normalize(imagenet_stats)

4. สร้างโมเดล

เพื่อความสะดวก เราจะประกาศฟังก์ชัน แล้วไปเรียกสร้างก่อน fit ด้วย Dropout แต่ละแบบ

  • เคสนี้เราจะใช้โมเดล models.resnet34
In [5]:
def get_learner(databunch):
    learner = cnn_learner(databunch, models.resnet34, 
                      ps=ps, wd=1e-1, 
                      metrics=accuracy, callback_fns=ShowGraph)
    learner.unfreeze()
    return learner

5. เริ่มต้นเทรนโมเดล

ปกติ ps จะมีค่า Default เท่ากับ 0.5 เราจะลองเทรนด้วย ps ต่ำมาก ไป สูงมาก เปรียบเทียบกับ Image Classification ep.1 ดูว่าจะเป็นอย่างไร

ลองเทรนโดยไม่ Dropout เลย ด้วย ps = 0.0

In [6]:
ps = 0.0

learner = get_learner(get_databunch())
learner.fit_one_cycle(epoch, max_lr=lr)
epochtrain_lossvalid_lossaccuracytime
00.4835160.4464400.86806500:46
10.5176330.5495590.84506100:44
20.3969940.5509720.86062200:43
30.2531080.6420360.85182700:44
40.1301080.4108550.89106900:44
50.0537300.3796630.90595400:44
60.0150570.3534310.92016200:44
70.0058270.3558780.91880900:44

ลองเทรนด้วย Dropout น้อย ๆ ด้วย ps = 0.25

In [7]:
ps = 0.25

learner = get_learner(get_databunch())
learner.fit_one_cycle(epoch, max_lr=lr)
epochtrain_lossvalid_lossaccuracytime
00.5394680.4588090.85385700:44
10.5884300.5358110.83964800:44
20.3942540.5992920.82747000:44
30.2617120.4446210.87618400:44
40.1247390.4573260.88227300:44
50.0634390.3382500.91069000:44
60.0144440.2793630.92354500:44
70.0062120.2809570.92895800:44

ลองเทรนด้วย Dropout กลาง ๆ ด้วย ps = 0.5 (ค่า Default)

In [8]:
ps = 0.5

learner = get_learner(get_databunch())
learner.fit_one_cycle(epoch, max_lr=lr)
epochtrain_lossvalid_lossaccuracytime
00.6665190.3149580.90527700:44
10.6198870.5747250.82882300:44
20.5466970.4580180.87550700:44
30.2965090.4449780.89445200:45
40.1211880.3483540.89580500:44
50.0801680.3361870.91069000:44
60.0236570.2796750.92557500:44
70.0106110.2851480.92828100:44

ลองเทรนด้วย Dropout มาก ๆ ด้วย ps = 0.75

In [9]:
ps = 0.75

learner = get_learner(get_databunch())
learner.fit_one_cycle(epoch, max_lr=lr)
epochtrain_lossvalid_lossaccuracytime
01.0767330.4044770.86671200:44
10.7914700.6478210.82747000:45
20.6010260.6294990.84573700:44
30.4384530.5175680.85994600:44
40.2585290.4385150.89377500:45
50.0778010.3849490.90257100:44
60.0416240.3626630.90663100:44
70.0219780.3489670.91069000:44

ลองเทรนด้วย Dropout ให้หมดเลย ด้วย ps = 1.0

In [10]:
ps = 1.0

learner = get_learner(get_databunch())
learner.fit_one_cycle(epoch, max_lr=lr)
epochtrain_lossvalid_lossaccuracytime
03.6119263.8765540.01217900:43
13.6139643.7920770.01217900:43
23.6148093.7156070.01556200:43
33.6139303.6789960.01353200:43
43.6149363.6617350.01488500:44
53.6138413.6535840.01826800:43
63.6114923.6498860.01623800:43
73.6107243.6495930.02029800:43

6. สรุป

เปรียบเทียบ การเทรนแต่ละ Dropout (ps) ในตารางดังนี้

psTimeAccuracyValid Loss
0.0005:5591.9%0.355
0.2505:5292.9%0.280
0.5005:5392.8%0.285
0.7505:5491.0%0.349
1.0005:452.0%3.649

หมายเหตุ

  • อันนี้เป็นการทดสอบแบบคร่าว ๆ ให้พอเห็นภาพ มีตัวแปรอีกหลายอย่าง
  • ใน Framework มีการใช้อีกหลายอัลกอริทึมโดย Default อาจทำให้ผลลัพธ์แตกต่างกันไป
  • แต่ละ learner มีการ Initial Weight ที่แตกต่างกัน
  • ps จะถูกใช้เป็น ค่า Probability ของ Dropout สำหรับ Layer สุดท้าย แต่ Layer ก่อนหน้านั้นจะใช้ ps/2
In [ ]:
 
In [ ]:
 

Credit

แชร์ให้เพื่อน:

Keng Surapong on FacebookKeng Surapong on GithubKeng Surapong on Linkedin
Keng Surapong
Project Manager at Bua Labs
The ultimate test of your knowledge is your capacity to convey it to another.

Published by Keng Surapong

The ultimate test of your knowledge is your capacity to convey it to another.

Enable Notifications    Ok No thanks