Tìm Hiểu Về Dropout Trong Deep Learning, Machine Learning

1. Dropout là gì, nó có ý nghĩa gì trong mạng neural network

Theo Wikipedia, thuật ngữ “dropout” đề cập đến việc bỏ qua các đơn vị (unit) (cả hai hidden unit và visible unit) trong mạng neural network.

Hiểu đơn giản là, trong mạng neural network, kỹ thuật dropout là việc chúng ta sẽ bỏ qua một vài unit trong suốt quá trình train trong mô hình, những unit bị bỏ qua được lựa chọn ngẫu nhiên. Ở đây, chúng ta hiểu “bỏ qua - ignoring” là unit đó sẽ không tham gia và đóng góp vào quá trình huấn luyện (lan truyền tiến và lan truyền ngược).

Về mặt kỹ thuật, tại mỗi giai đoạn huấn luyện, mỗi node có xác suất bị bỏ qua là 1-p và xác suất được chọn là p

2. Tạo sao chúng ta cần dropout

Giả sử rằng bạn hiểu hoàn toàn những gì đã nói ở phần 1, câu hỏi đặt ra là tại sao chúng ta cần đến dropout, tại sao chúng ta cần phải loại bỏ một vài các unit nào đó trong mạng neural network?

Câu trả lời cho câu hỏi này là để chống over-fitting

Khi chúng ta sử dụng full connected layer, các neural sẽ phụ thuộc “mạnh” lẫn nhau trong suốt quá trình huấn luyện, điều này làm giảm sức mạng cho mỗi neural và dẫn đến bị over-fitting tập train.

3. Dropout

Đọc đến đây, bạn đã có một khái niệm cơ bản về dropout và động lực - động cơ để chúng ta sử dụng nó. Nếu bạn chỉ muốn có cái nhìn tổng quan về dropout trong neural network, hai sections trên đã cung cấp đầy đủ thông tin cho bạn, bạn có thể dừng tại đây. Phần tiếp theo, chúng ta sẽ nói kỹ hơn về mặt kỹ thuật của dropout.

Trước đây, trong machine learning, người ta thường sử dụng regularization để ngăng chặn over-fititng. Regularization làm giảm over-fitting bằng cách thêm yếu tố “phạt” vào hàm độ lỗi (loss function). Bằng việc thêm vào điểm phạt này, mô hình được huấn luyện sẽ giúp các features weights giảm đi sự phụ thuộc lẫn nhau. Đối với những ai đã sử dụng Logistic Regression rồi thì sẽ không xa lạ với thuật ngữ phạt L1(Laplacian) và L2 (Gaussian).

Dropout là một kỹ thuật khác, một cách tiếp cận khác để regularization trong mạng neural netwoks.

Kỹ thuật dropout được thực hiện như sau:

Trong pha train: với mỗi hidden layer, với mỗi trainning sample, với mỗi lần lặp, chọn ngẫu nhiên p phần trăm số node và bỏ qua nó (bỏ qua luôn hàm kích hoạt cho các node bị bỏ qua).

Trong pha test: Sử dụng toàn bộ activations, nhưng giảm chúng với tỷ lệ p (do chúng ta bị miss p% hàm activation trong quá trình train).

Hình ảnh Mô tả về kiến trúc mạng có và không có dropout

4. Một số đặc điểm rút ra được khi huấn luyện nhiều mô hình khác nhau sử dụng dropout

  • Dropout ép mạng neural phải tìm ra nhiều robust features hơn, với đặc điểm là chúng phải hữu ích hơn, tốt hơn, ngon hơn khi kết hợp với nhiều neuron khác.

  • Dropout đòi hỏi phải gấp đôi quá trình huấn luyện để đạt được sự hội tụ. Tuy nhiên, thời gian huấn luyện cho mỗi epoch sẽ ít hơn.

  • Với H unit trong mô hình, mỗi unit đều có xác xuất bị bỏ qua hoặc được chọn, chúng ta sẽ có 2^H mô hình có thể có. Trong pha test, toàn bộ network được sử dụng và mỗi hàm activation được giảm đi với hệ số p.

  • Một số nghiên cứu chỉ ra rằng, khi sử dụng Dropout và Batch Normalization (BN) cùng nhau thì kết quả rất tệ, trong cả lý thuyết và thực nghiệm, ví dụ nghiên cứu ở papper “Understanding the Disharmony between Dropout and Batch Normalization by Variance Shift”, nguồn https://arxiv.org/abs/1801.05134, nhóm tác giả giải thích về mặt lý thuyết rằng: “đối với một neural, Dropout sẽ thay đổi phương sai của nó khi chúng ta chuyển trạng thái từ trian sang test. Còn BN thì không, BN vẫn tích luỹ đầy đủ thông tin trong quá trình huấn luyện. Do Dropout làm thay đổi phương sai nên sẽ xảy ra hiện tượng không đồng nhất về phương sai, dẫn đến hành vi suy luận không chắc chắn dẫn đến suy luận bị sai nhiều. Đặc biệt là khi kết hợp dropout và BN thì khiến cho suy luận càng sai lầm trầm trọng. “. Cho nên, trong một số trường hợp/bài toán chúng ta có thể dùng Dropout, trong một số trường hợp/ bài toán, người ta sử dụng BN và không sử dụng dropout.

  • Người ta thường dùng hệ số dropout là 0.5. Lý giải cho việc này, bạn có thể đọc bài báo http://papers.nips.cc/paper/4878-understanding-dropout.pdf. Nói nôm là việc sử dụng giảm 50% của dropout giúp kết quả đạt được là tốt nhất so với các phương pháp chuẩn hoá khác.

5. Thực nghiệm trong keras

Những vấn đề nói ở trên chỉ là lý thuyết. Bây giờ chúng ta sẽ bắt tay vào làm thực tế. Để xem thử dropout hoạt động như thế nào, chúng ta sẽ xây dựng mô hình deep net sử dụng keras và sử dụng tập dữ liệu cifar-10. Mô hình chúng ta xây dựng có 3 hidden layer với kích thước lần lượt là 64, 128, 256 và 1 full connected layer có kích thước 512 và output layer có kích thước 10 (do mình có 10 lớp).

Chúng ta sử dụng hàm kích hoạt là ReLU trên các hidden layer và sử dụng hàm sigmoid trên output layer. Sử dụng hàm lỗi categorical cross-entropy.

Trong trường hợp mô hình có sử dụng dropout, chúng ta sẽ set dropout ở tất cả các layer và thay đổi tỷ lệ dropout nằm trong khoảng từ 0.0 đến 0.9 với bước nhảy là 0.1.

Mô hình setup với số epochs là 20. Bắt đầu xem nào.

Đầu tiên, chúng ta sẽ load một vài thư viện cần thiết

 1import numpy as np
 2import os
 3
 4import keras
 5
 6from keras.datasets import cifar10
 7from keras.models  import Sequential
 8from keras.layers import Dense, Dropout, Activation, Flatten
 9from keras.layers import Convolution2D, MaxPooling2D
10from keras.optimizers import SGD
11from keras.utils import np_utils
12from keras.preprocessing.image import ImageDataGenerator
13import matplotlib.pyplot as plt
14
15from pylab import rcParams
16rcParams['figure.figsize'] = 20, 20
17
18from keras.datasets import cifar10
19
20(X_train, y_train), (X_test, y_test) = cifar10.load_data()
21
22
23print("Training data:")
24print("Number of examples: ", X_train.shape[0])
25print("Number of channels:",X_train.shape[3])
26print("Image size:",X_train.shape[1], X_train.shape[2], X_train.shape[3])
27
28print("Test data:")
29print("Number of examples:", X_test.shape[0])
30print("Number of channels:", X_test.shape[3])
31print("Image size:",X_test.shape[1], X_test.shape[2], X_test.shape[3])

Kết quả

1Training data:
2Number of examples:  50000
3Number of channels: 3
4Image size: 32 32 3
5Test data:
6Number of examples: 10000
7Number of channels: 3
8Image size: 32 32 3

Chúng ta có 50000 hình train, và 10000 hình test. Mỗi hình là một ảnh RGB có kích thước 33x32x3 pixel.

Hình ảnh dataset cifar 10

Tiếp theo, chúng ta sẽ chuẩn hoá dữ liệu. Đây là 1 bước quan trọng trước khi huấn luyện mô hình

 1print( "mean before normalization:", np.mean(X_train))
 2print( "std before normalization:", np.std(X_train))
 3
 4mean=[0,0,0]
 5std=[0,0,0]
 6newX_train = np.ones(X_train.shape)
 7newX_test = np.ones(X_test.shape)
 8for i in range(3):
 9    mean[i] = np.mean(X_train[:,i,:,:])
10    std[i] = np.std(X_train[:,i,:,:])
11
12for i in range(3):
13    newX_train[:,i,:,:] = X_train[:,i,:,:] - mean[i]
14    newX_train[:,i,:,:] = newX_train[:,i,:,:] / std[i]
15    newX_test[:,i,:,:] = X_test[:,i,:,:] - mean[i]
16    newX_test[:,i,:,:] = newX_test[:,i,:,:] / std[i]
17
18
19X_train = newX_train
20X_test = newX_test
21
22print("mean after normalization:", np.mean(X_train))
23print("std after normalization:", np.std(X_train))
1mean before normalization: 120.70756512369792
2std before normalization: 64.1500758911213
3mean after normalization: 0.9062499999999979
4std after normalization: 0.4227421643271468

Full code đoạn huấn luyện

  1
  2
  3# In[3]:Specify Training Parameters
  4
  5batchSize = 512                   #-- Training Batch Size
  6num_classes = 10                  #-- Number of classes in CIFAR-10 dataset
  7num_epochs = 100                   #-- Number of epochs for training
  8learningRate= 0.001               #-- Learning rate for the network
  9lr_weight_decay = 0.95            #-- Learning weight decay. Reduce the learn rate by 0.95 after epoch
 10
 11
 12img_rows, img_cols = 32, 32       #-- input image dimensions
 13
 14Y_train = np_utils.to_categorical(y_train, num_classes)
 15Y_test = np_utils.to_categorical(y_test, num_classes)
 16
 17
 18
 19batchSize = 512                   #-- Training Batch Size
 20num_classes = 10                  #-- Number of classes in CIFAR-10 dataset
 21num_epochs = 100                   #-- Number of epochs for training
 22learningRate= 0.001               #-- Learning rate for the network
 23lr_weight_decay = 0.95            #-- Learning weight decay. Reduce the learn rate by 0.95 after epoch
 24
 25
 26img_rows, img_cols = 32, 32       #-- input image dimensions
 27
 28Y_train = np_utils.to_categorical(y_train, num_classes)
 29Y_test = np_utils.to_categorical(y_test, num_classes)
 30
 31
 32# In[4]:VGGnet-10
 33
 34
 35from keras.layers import Conv2D
 36import copy
 37result = {}
 38y = {}
 39loss = []
 40acc = []
 41dropouts = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
 42for dropout in dropouts:
 43    print("Dropout: ", (dropout))
 44    model = Sequential()
 45
 46    #-- layer 1
 47    model.add(Conv2D(64, (3, 3),
 48                            border_mode='valid',
 49                            input_shape=( img_rows, img_cols,3)))
 50    model.add(Dropout(dropout))
 51    model.add(Conv2D(64, (3, 3)))
 52    model.add(Dropout(dropout))
 53    model.add(Activation('relu'))
 54    model.add(MaxPooling2D(pool_size=(2, 2)))
 55
 56    ##--layer 2
 57    model.add(Conv2D(128, (3, 3)))
 58    model.add(Dropout(dropout))
 59    model.add(Activation('relu'))
 60    model.add(MaxPooling2D(pool_size=(2, 2)))
 61
 62    ##--layer 3
 63    model.add(Conv2D(256, (3, 3)))
 64    model.add(Dropout(dropout))
 65    model.add(Activation('relu'))
 66    model.add(MaxPooling2D(pool_size=(2, 2)))
 67
 68    ##-- layer 4
 69    model.add(Flatten())
 70    model.add(Dense(512))
 71    model.add(Activation('relu'))
 72
 73    #-- layer 5
 74    model.add(Dense(num_classes))
 75
 76    #-- loss
 77    model.add(Activation('softmax'))
 78
 79    sgd = SGD(lr=learningRate, decay = lr_weight_decay)
 80    model.compile(loss='categorical_crossentropy',
 81                  optimizer='sgd',
 82                  metrics=['accuracy'])
 83
 84    model_cce = model.fit(X_train, Y_train, batch_size=batchSize, epochs=20, verbose=1, shuffle=True, validation_data=(X_test, Y_test))
 85    score = model.evaluate(X_test, Y_test, verbose=0)
 86    y[dropout] = model.predict(X_test)
 87    print('Test score:', score[0])
 88    print('Test accuracy:', score[1])
 89    result[dropout] = copy.deepcopy(model_cce.history)
 90    loss.append(score[0])
 91    acc.append(score[1])
 92
 93
 94
 95# In[5]: plot dropout
 96import numpy as np
 97import matplotlib.pyplot as plt
 98
 99width = 0.1
100
101plt.bar(dropouts, acc, width, align='center')
102
103plt.tick_params(axis='both', which='major', labelsize=35)
104plt.tick_params(axis='both', which='minor', labelsize=35)
105
106plt.ylabel('Accuracy',size = 30)
107plt.xlabel('Dropout', size = 30)
108plt.show()
109
110
111# In[6]: plot non drop out
112
113import numpy as np
114import matplotlib.pyplot as plt
115
116width = 0.1
117
118plt.bar(dropouts, loss, width, align='center',color = 'green')
119
120plt.tick_params(axis='both', which='major', labelsize=35)
121plt.tick_params(axis='both', which='minor', labelsize=35)
122
123plt.ylabel('Loss',size = 30)
124plt.xlabel('Dropout', size = 30)
125plt.show()

Hình ảnh Kết quả

Nhìn hình kết quả ở trên, chúng ta có một số kết luận nhỏ như sau:

Giá trị dropout tốt nhất là 0.2, khoảng dropout cho giá trị chấp nhận được là nằm trong đoạn từ 0 đến 0.5. Nếu dropout lớn hơn 0.5 thì kết quả hàm huấn luyện trả về khá tệ.

Giá trị độ chính xác còn khá thấp => 20 epochs là chưa đủ, cần huấn luyện nhiều hơn nữa.

Cảm ơn các bạn đã theo dõi. Hẹn gặp bạn ở những bài viết tiếp theo.

Comments