Chọn cách code nào để tạo mô hình Transfer Learning "Tốt" - keras

transfer-learning

#1

Theo như mình tìm hiểu có 2 kiểu code để tạo một cấu trúc cho tranfer-learning:

Cách 1:

base_model=MobileNet(weights='imagenet',include_top=False)

for layer in base_model.layers:
   layer.trainable=False

x=base_model.output
x=GlobalAveragePooling2D()(x)
x=Dropout(0.3)(x)
preds=Dense(10,activation='softmax')(x)
model=Model(inputs=base_model.input,outputs=preds)

Cách 2:

base_model = MobileNet(weights='imagenet', include_top=False)
train_features = base_model.predict(X_train)
model = Sequential()
model.add(GlobalAveragePooling2D(input_shape=train_features.shape[1:]))
model.add(Dropout(0.3))
model.add(Dense(10, activation='softmax'))

Mình thử train model của mình thì thấy cách 2 luôn nhanh hơn và acc thường luôn cao hơn tầm 40% dù trên tập train acc cả 2 cái đều tầm 98, 99%. Thời gian train cho mỗi Epoch ở cách một tầm 20-30s còn ở cách 2 chỉ tầm 2s cho mỗi Epoch (cả 2 đều dùng GPU). Mình không hiểu tại sao cách 1 lại có thể ra acc tệ như vậy.

Mọi người thường dùng cách code nào và có thể chia sẻ kinh nghiệm về nó không?


#3

Một số khác biệt mình thấy giữa 2 cách như sau:

Cách 1:

Base_model sẽ không được cập nhật các parameters trong quá trình training.

Trong quá trình forward của cả model, base_model cũng sẽ tham gia vào quá trình đó, nghĩa là base_model sẽ được gọi cho mỗi batch để tính ra features cho các layers sau đó của bạn. Đây là lí do cách 1 chậm.

Một vài layers sẽ chỉ được kích hoạt trong quá trình training (ví dụ BatchNorm, Dropout), do đó, bởi vì base_model là một phần của model tổng thể, nên khi training có thể kích hoạt các layers đó. Đây là sự khác biệt so với cách 2.

Cách 2:

Base_model cũng vẫn sẽ không được cập nhật các parameters.

Base_model chỉ được gọi 1 lần để tính cho tất cả samples, ở quá trình predict này, một số layers mình kể trên sẽ không được sử dụng.

Model chính lúc này rất đơn giản, do không phải tính đi tính lại các features bằng base_model cho mỗi lần forward. Đây là lí do cách 2 chạy nhanh hơn.

Mình hiện tại không thể giải thích tại sao accuracy của cách 2 lại tệ hơn cách 1 vì thấy nó còn phụ thuộc vào nhiều yếu tố khác nữa. Nên mình chỉ liệt kê một vài khác biệt mình nhận thấy ra đây hi vọng các bạn khác sẽ bổ sung thêm.


#4

Ai biết cách code giống kiểu 2 trong Pytorch ko ạ. Em muốn thử xem nó có nhanh hơn không mà thấy toàn kiểu code giống cách 1


#5

Như mình code ở đây là không kích hoạt những layer đó nhỉ, mặc định sẽ là giống với cách 2 vì lấy ra feature thì cũng phải cho input đi qua hết base_model mà nhỉ.


#6

Nếu thử thành công, bạn comment vào đây xem kết quả có như mình nói ở trên hay không nhé


#7

Trong cách 1, base_model là một phần trong model tổng thể của bạn (bạn thử in graph ra xem thế nào), việc thiết lập trainable = False chỉ để nói rằng các weights trong các layers đó sẽ không được cập nhật trong quá trình học.


#8

Cách 1 là cố định base model, nghĩa là parameters trong base model không được cập nhật Còn cách 2 thì base model được train luôn. Còn tại sao acc ra thấp thì b phải xem data của b như thế nào, có nhiều cách transfer learning nhưng phải xem vào data lớn hay nhỏ nữa. Còn b hỏi trong pytorch code như thế nào thì mình gợi ý là b set parameter requires_grad = False ở base model là được. :smiley:


#9

cách 2 base model đâu có được train đâu nhỉ.


#10

có bài viết nào nói rõ cái này không nhỉ? Mình vẫn hơi mơ hồ.


#11

à mình nhầm xem chưa kĩ cách 2 vẫn k đc train nha b, cách 2 mình thấy là b đang inference nó thôi


#12

Mình đã thử bằng cái set requires_grad = False cho 1 số layer cho base_model bằng pytorch. Tốc độ nhanh hơn hẳn nhưng acc cũng drop cực mạnh.