[Chia sẻ] [Kaggle] Quick, Draw! Doodle Recognition Challenge 11th Solution


#1

Chào mọi người,
Cuộc thi Quick, Draw! Doodle Recognition Challenge mới kết thúc ngày hôm nay. Team mình (Draw me a star) may mắn đứng thứ hạng 11/1316 trên private leader board. Thay mặt cho team, mình xin phép chia sẻ solution cho bài toán này, hi vọng nó sẽ giúp ích cho các bạn.

1. Đề bài

Yêu cầu của bài toán là nhận dạng bức ảnh được vẽ bằng tay được người chơi vẽ tại đây . Sau đây là ví dụ

2. Data

  • 340 class
  • ~50,000,000 ảnh tất cả
  • Ảnh được vẽ từ những người chơi đến từ các quốc gia (countrycode), thời gian (timestamp) khác nhau
  • Data của ảnh được cho dưới dạng stroke bao gồm tọa độ (x, y) mà các nét vẽ chạy qua

3. Một chút nhìn nhận về bài toán

  • Số lượng class khá lớn
  • Có những bức ảnh mà có thể thuộc một hay nhiều class mà con người cũng khó có thể phân loại đúng. VD: alarm vs clock, bus vs school bus, caffe cup vs cup…
  • Data lớn và unbalanced
  • Có khá nhiều nhiễu, nhiều ảnh được gán nhãn sai. Công việc gán nhãn của training set được hoàn thành bởi một model trước đó của Google.

4. Approach

Finally solution của team mình như sau

4.1 Image based

Với số lượng data lớn như vậy chúng ta sẽ chọn cách nào giữa train từ đầu (scratch) hay sử dụng pretrained. Câu trả lời là cả hai đều hội tụ (convex) giống nhau, nhưng pretrained hội tụ nhanh hơn. Chúng mình sử dụng những model sau:

  • resnet50
  • densenet169
  • xception
  • SEResnet50
  • SEResnext101
  • SEResnext50

Trước tiên chúng mình thử nghiệm với các data nhỏ và nhận thấy rằng:

  • Batch size lớn tốt khi có nhiều noise
  • Image size lớn sẽ khiến performance tốt hơn

Vì team mình mỗi người train một model, resource khác nhau, nên mình không thể nhớ hết được setting của mỗi model. Tiêu chí khi train model là ảnh ít nhất là 128x128, batch size to nhất có thể. Nói một cách chung chung thì các model trên được train với các thông số sau

  • Full data
  • Image size: 128, 256
  • Batch size: >256
  • Augmentation: None. Nó ko giúp ích được nhiều vì số lượng data đã quá lớn. Thêm vào chỉ chậm model hơn mà thôi.

4.2 Stroke based

Như mình đã giới thiệu ở trên, data được cho dưới dạng stroke. Như vậy, dựa vào các nét vẽ như thứ tự vẽ, thời gian vẽ là dữ liệu có dạng thứ tự, theo thời gian, mình có thể sử dụng LSTM để phân loại.
Team mình không tập trung nhiều vào phần này lắm, chủ yếu sử dụng những idea cơ bản từ public kernel trong cuộc thi. Mãi 2 tuần cuối mới bắt đầu bắt tay làm model LSTM.

  • Base kernel
  • Sử dụng Bidirectional
  • 3 Layers LSTM và 1 layer GRU
  • Sử dụng attention sau lớp LSTM cuối (1)
  • Batch norm tốt hơn dropout
  • Concat average and max pooling ở các lớp CNN đầu (2)
  • Concat (1) và (2) => BatchNorm trước khi qua FC layers cuối
  • Train full data

5. Kết quả

5.1 Image based

Best single model: SEResnext50

  • Pulic LB: 0.943
  • Private LB: 0.941
  • Overfit: 0.2%

Sử dụng 2TTA (Normal + Horizontal Flip):

  • Pulic LB: 0.944
  • Private LB: 0.942
  • Overfit: 0.2%

Đến giờ mình chưa thấy ai trong diễn đàn thông báo là có model ko bị overfit khi train với full data. Khi bạn train với small data (~17tr data) thì có thể không bị overfit. Nhưng với full data thì mọi chuyện sẽ khác Mình để ý top1 cũng bị overfit với một khoảng cách tương tự như vậy. Có lẽ việc sử dụng mỗi image làm feature dẫn đến tình huống này.

Mình có check lại submission trước, khi mình train model image với các feature sau:

  • Countrycode (Embedding)
  • LSTM cho image

Thì không thấy hiện tượng overfit. Đây là một điều khá đáng tiếc của team, vì trong quá trình train, mình nhận thấy kết quả không tăng nhiều khi thêm 2 features này vào. Nhưng có vẻ nó giúp cho model tránh được overfit.

5.2 Stroke based

Best model:

  • Public LB: 0.93490
  • Private LB: 0.93411

Có thể nói LSTM model không bị overfit như Image based model.

5.3 Ensemble

Kết quả cuối cùng của bọn mình là weighted average của 14 model với các thể loại feature khác nhau :smiley: .

  • Public LB: 0.948
  • Private LB: 0.947

5.4 Post processing (secret sauce)

Với số điểm kia thì top mình chỉ đứng ở vị tri 2x trên bảng xếp hạng. Đây là key technique giúp team mình đạt thứ hạng cao với 0.5% cho public LB, và 0.3% cho private LB.
Nhận xét quan trọng:

Số lượng test set là: 112200 ảnh. Số lượng class là 340 => 112200 / 340 = 330 chẵn. Có vẻ như ở tập test set, số lượng ảnh của mỗi class mình cần dự đoán là bằng nhau. Chúng ta có thể verifty điều này bằng cách submit một kết quả mà tất cả test set đều giống nhau. Ở bài toán này, metric là MAP@3. Như vậy nếu giả thiết ở trên đúng thì kết quả public LB sẽ là: 330 * (1 + 2/3 + 1/3) / 112200 = 0.005. Nhìn vào sample submission benchmark, nó chính là: 0.005. Perfect !!!. Như vậy giả thiết về sự cân bằng ở test set là 99% đúng.

Với giả thiết trên, mình sử dụng một kỹ thuật là Optimization được sử dụng tại cuộc thi này bởi một thành viên trong team.

Chúng mình khá tự tin với post-processing này, và cuối cùng nó là người ghánh kèo trong cuộc thi này :slight_smile:

6 Teamwork và funny moments

  • Team 7 người, sinh sống tại 5 quốc gia. Việc phân chia task rất quan trọng
  • Chúng mình họp team vào mỗi cuối tuần, lên plan cụ thể và rõ ràng. Nếu gặp vấn đề cần họp team gấp.
  • Team giao tiếp trên Slack và quản lý source code bằng gitlab. Kết quả của model đều được update trên đó dù cao hay thấp.
  • Team có một thầy bói, thánh phán, thánh lô đề sổ xố. Bạn này sắp tới sẽ là Kaggle master trẻ nhất Việt Nam (tính đến hiện tại theo mình biết). Team mình k cần quá nhiều submission cho những model con :smiley:. Thay vào đó gửi Local CV và nhận kết quả phán từ bạn ấy =)). Độ chính xác là 96.69%
  • Team làm việc rất vui vẻ, thoải mái, k áp lực :wink:

7 Meta data

  • 2x1080Ti + 1x1080Ti + 1x1080Ti + 1x1080 + 1*V100 + 2 * P40
  • Thời gian train một epoch (full data): >1 ngày.
  • 10522 LOC
  • over 300 commits
  • 9 branches
  • 8 merge request
  • 11 issuse
  • 10k slack message

Cám ơn mọi người đã đọc hết bài viết.
Update: Mình xin chia sẻ code tại đây:


[Chia sẻ] [Kaggle] Code of Quick, Draw! Doodle Recognition Challenge 11th Solution
#2

Cám ơn anh đã chia sẻ. Bài viết rất hữu ích và đáng để học hỏi ạ!


#3

:)) Viết bài chia sẻ cách đoán LB đi em


#4

Cảm ơn anh và team đã chia sẻ. Rất mong bạn Hậu ở trên chia sẻ thêm cái anh Bắc bảo.


#5

Chúc mừng anh và đồng đội. Cảm ơn anh đã có những chia sẻ bổ ích cho mọi người :slight_smile:


#6

ngxbac: team có thể chia sẻ code dc ko Bắc :slight_smile:


#7

Chào bạn, rất xin lỗi vì trả lời trễ. Mình chia sẻ code ở topic này. Mong nó giúp ích cho bạn


#8

Hi anh! Cảm ơn anh vì chia sẻ rất bổ ích. Em có một thắc mắc nhỏ là làm sao mình tính được Overfit rate là 0.2% vậy ạ ?