Custom Loss là cái giống gì? Vì sao phải dùng?

Chào các anh em Mì AI, hôm nay chúng ta sẽ cùng tìm hiểu về Custom Loss – hàm loss tự tạo – trong ML, DL với Keras nhé.

Lâu lắm rồi mới viết bài cho anh em đây. Dạo này bận nên tranh thủ được thời gian là quay video cho nhanh kaka.

Trước khi bắt đầu bài này mình cũng xin nói luôn là mình giải thích hoàn toàn bằng kinh nghiệm, bằng kiểu Mì AI cho dễ hiểu cho các bạn newbie. Mong các cao thủ đi qua giúp đỡ thêm ah.

Okie, let’s go!

Phần 1 – Custom Loss là gì?

Trước khi đi sâu vào tìm hiểu Custom Loss code ra sao? Triển khai như nào thì chúng ta sẽ đi tìm hiểu xem custom loss là gì?

Custom Loss dịch nôm na là hàm loss được custome, haha! Đùa chút cho vui thôi, tóm lại là anh em có thể viết hàm loss riêng hoặc chỉnh sửa lại hàm loss sẵn có cho phù hợp với nhu cầu đặc biệt nào đó của anh em.

Nếu anh em cần tìm hiểm xem Loss là gì thì mình đã có một bài về món đó rồi, anh em đọc lại tại link này nhé: https://www.miai.vn/2020/06/12/oanh-gia-model-ai-theo-cach-mi-an-lien-chuong-1-loss-va-accuracy/

Phần 2 – Tại sao phải custom cái hàm loss cho mệt?

Đúng! Tội gì phỉa custom loss làm gì cho mệt nhỉ? Haha! Trước mình cũng nghĩ như thế cho đến một ngày ….. nhận ra nó không thế 😀

Bây giờ để các bạn hiểu lý do phải Custom Loss thì chúng ta cùng xét qua vài ví dụ sau.

Ví dụ 01

Chúng ta làm một bài toán với input X và vector output predict label yhat và vector true label y của chúng ta là một vector có độ dài n. Bây giờ khi chúng ta sử dụng loss mặc định (ví dụ Mean Square Error, RMSE hay Cross Entropy…) thì hàm loss sẽ tính toán đầy đủ trên n phần tử của vector yhat và y. Tuy nhiên trong một số trường hợp nào đó, ví dụ bằng Data Knowledge của bạn, bạn thấy rằng nên loại 02 phần tử đầu của 2 vector yhat và y ra khỏi quá trình tính toán loss vì nó không có ý nghĩa chẳng hạn. Đó là lúc bạn phải custom lại hàm loss của bạn đó.

custom loss

Ví dụ 02. Bài toán Coin Segmentation

Giả sử giờ chúng ta làm bài toán Coin Segmentation – phân tách các đồng xu nhé. Và giả sử input và output của chúng ta được yêu cầu như sau:

  • Input: Hình ảnh các đồng xu
  • Output: Phân loại các điểm ảnh trong input thành 0 – Vùng ảnh nền (màu trắng), 1 – Vùng thuộc đồng xu (màu vàng) và 2 – Vùng biên giữa các đồng xu (màu xanh).
custom loss in coin segmentation

Với bài toán này có nhiều cách làm lắm, nhưng mình giả sử bị ép làm theo cách trên để demo custom loss ấy mà :D. Các bạn chú ý nhé!

Rồi, đây là một bài toán classify thông thường và giả sử loss của nó là $L$, trong đó:

$$L=(L_{coin} + L_{no coin} + L_{border})$$

Bây giờ nhìn vào hình thì ta sẽ thấy đa phần các pixel trong hình là coin hoặc no_coin. Điều đó dẫn đến mô hình của chúng ta sẽ thiên về dự đoán các pixel vào 1 trong 2 lớp đó dẫn đến vùng border sẽ ít , các đồng xu sẽ bị lem vào nhau, không đáp ứng được nhu cầu của bài toán.

Và đây là lúc chúng ta cần custom bài toán đây. Chúng ta sẽ thêm vào 2 tham số $\alpha$ và $\beta$ (đều là số đủ nhỏ và < 1) vào $L_{coin}$ và $L_{no_coin}$ để trừng phạt mạnh hơn việc nhận diện sai border. Và ta có hàm loss mới:

$$L=(\alpha*L_{coin} + \beta*L_{no coin} + L_{border})$$

Hi vọng các bạn đã hiểu qua qua lý do cần phải custom loss, bây giờ chúng ta sẽ xem thử code thực tế bằng Python cho dễ nhé.

Phần 3 – Code với Python, Keras

Với hàm loss mặc định thì chúng ta cứ làm mỗi việc gọi tên hàm loss ra thôi. Ví dụ với bài toán Nhận dạng tiền Việt Nam với Transfer Learning (VGG16 CNN Classify) mình vừa làm trên Mì AI đi nhé.

# Them cac layer FC va Dropout
    x = Flatten(name='flatten')(output_vgg16_conv)
    x = Dense(4096, activation='relu', name='fc1')(x)
    x = Dropout(0.5)(x)
    x = Dense(4096, activation='relu', name='fc2')(x)
    x = Dropout(0.5)(x)
    x = Dense(4, activation='softmax', name='predictions')(x)

    # Compile
    my_model = Model(input=input, output=x)
    my_model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])Code language: PHP (php)

Đó các bạn để ý đoạn loss=’categorical_crossentropy’, đây là hàm loss crossentropy mặc định.

Hàm loss này thì đã có nhiều bài viết về nó trên google, nếu bạn cần thêm trợ giúp hãy post lên Group trao đổi, chia sẻ: https://facebook.com/groups/miaigroup để cùng thảo luận nhé!

Rồi đó là ví dụ dùng loss mặc định, giờ ta thử code một bài toán khác, sẽ dùng loss custom nhé.

Giả sửa chúng ta đang làm bài toán dự đoán hồi quy Regression về nhiệt độ, đổ ẩm và áp suất của phòng thí nghiệm dựa vào 10 giá trị sensor đầu vào. Điều đó có nghĩa là vector input sẽ là một vector $x$ có độ dài 10 và output sẽ là vector $y$ có độ dài là 3 gồm $y_{1}$ – nhiệt độ, $y_{2}$ – độ ẩm và $y_{3}$ – áp suất.

custom loss

Và như bao bài toán Regression khác, chúng ta thực hiện xây dựng mạng NN (ví dụ thế cho hoành) như sau:

model = keras.models.Sequenial()
model.add(Dense(128, input_shape=(10,), activation='relu'))
model.add(Dense(64, activation='relu'))
model.add(Dense(16, activation='relu'))
model.add(Dense(3, activation='linear'))
model.compile(loss="mse", optimizer='adam')Code language: JavaScript (javascript)

Các bạn focus vào mấy điểm sau:

  • Input là 10, chính là độ dài của vector $x$
  • Layer dense cuối cùng có 3 unit và hàm activation là linear thông thường vì đây là bài toán hồi quy.
  • Hàm loss đang dùng MSE

Okie, và mọi thứ ngon lành cành đào thôi! Nhưng model nào thì cũng có sai sót và model này cũng vậy, đôi khi nó sẽ dự đoán sai (lệch so với giá trị thực). Và bạn nhận được lệnh, okie sai thì là tất nhiên nhưng ông cần đảm bảo cho tôi là ưu tiên dự đoán đúng nhiệt độ và độ ẩm, áp suất thì sai tý cũng được. Và giờ bạn phải làm sao?

Câu trả lời là bạn cần custom hàm loss để phạt nặng hơn việc nhận sai nhiệt độ và độ ẩm, coi nhẹ hơn ông áp suất. Let’s do it!

def custom_mse_loss(y_true, y_pred):
    mse_loss = K.square(y_pred - y_true)  
    mse_loss = loss * [0.4, 0.4, 0.2]  
    mse_loss = K.sum(loss, axis=1)  

    return mse_lossCode language: JavaScript (javascript)

Đó đó, chúng ta tính loss xong thì nhân ngay với 1 cái vector [0.4, 0.4,0.2] để đánh trọng số cho cái loss của chúng ta, ưu tiên $y_{1}$ – nhiệt độ, $y_{2}$ – độ ẩm và coi nhẹ hơn tý $y_{3}$ – áp suất. Okie và bây giờ là ghép vào code nào!

model.compile(loss="custom_mse_loss", optimizer='adam')Code language: JavaScript (javascript)

That’s all. Simple đúng không các bạn?

Bài này mình không có ý định cover tất cả các case của Custom Loss mà mình chỉ muốn giới thiệu cho các bạn biêt rằng có khái niệm Custom Loss để các bạn dùng khi cần thiết. Khi nào bạn cần tối ưu hoá model, fine tune, nâng cao độ chính xác…. thì các bạn sẽ ngay lập tức nảy sinh nhu cầu custom lại loss và hãy nhớ tới bài này nhé.

Còn bây giờ, xin tạm biệt nhé!

#MìAI

Fanpage: http://facebook.com/miaiblog
Group trao đổi, chia sẻ: https://www.facebook.com/groups/miaigroup
Website: https://miai.vn
Youtube: http://bit.ly/miaiyoutube

Related Post

Leave a Reply

Your email address will not be published. Required fields are marked *