[AIVIVN-Face Recognition] 2nd solution

aivivn_face_recognition

#1

Mình chia sẻ source code, guideline và solution chi tiết cho cuộc thi nhận dạng người nổi tiếng.

https://drive.google.com/open?id=1LKVqvUm83hFazCoji683XL14xtfB9wQr

Đây là một dòng để khác bài giới thiệu của anh Top 1 :smiley:

Tóm tắt

Submission cuối cùng của nhóm mình là một ensemble (với equal weighting) của 4 loại architectures sau:

  1. ArcFace (https://github.com/ZhaoJ9014/face.evoLVe.PyTorch)
  2. CosFace (cùng repo. 1.)
  3. SphereFace (cùng repo. 1.)
  4. Two-layer MLP viết bằng Keras Ngoài ra, một bước post-processing nhỏ được áp dụng để xử lý nhãn thứ “1000” có trong test data. Tất cả các thí nghiệm được thực hiện với 2 con 1080Ti.

Chi tiết

0. Tiền xử lý

Dùng Face Detector của (https://github.com/deepinsight/insightface) để detect và align.

1. ArcFace, CosFace, SphereFace

Một số đặc điểm được nhóm mình rút ra từ train data và cách những deep face recognition models như ArcFace hoạt động là:

  • Số lượng examples giữa những classes khá chênh lệch nhau, có khoảng gần 400 classes chỉ có duy nhất 1 hình.
  • Trong forward pass của các models trên, image embedding và head (classifier) weight phải được l2 normalized trước khi thực hiện những bước tính toán tiếp theo. Những điểm này trùng lặp với setup của paper “Low-Shot Learning with Imprinted Weights” (https://arxiv.org/pdf/1712.07136.pdf). Thay vì init. lại head network 1 cách ngẫu nhiên như bình thường, phương pháp imprinting weights được sử dụng để tạo ra điểm khởi tạo tốt hơn:
    • Embeddings cho tất cả những hình cùng class i sẽ được tính, trung bình của các embeddings này sẽ là vector weight khởi tạo tương ứng với class i.
    • Lặp lại bước trên cho tất cả các classes (i=0,…,999) có trong train data. Kết quả cuối cùng là 1 array có shape (1000, 512). Với mỗi file checkpoint của backbone IR-50 (có tổng cộng là 3 cung cấp bởi tác giả repo), nhóm mình sẽ tính được 1 cái head weight tương ứng. 3 cặp backbone - head weights này được load vào từng face rec. model; mỗi model sẽ được train với tất cả hình ảnh có trong train dataset trong vòng 30 epochs. Sau khi hoàn tất training, để lấy được softmax scores trên bộ test thì cần phải modify 1 chút trong file head/metrics.py như sau:
class ArcFace(nn.Module):
    ...
    def forward(self, input, label):
        ...
        if not self.training:
            # For inference
            return F.softmax(cosine * self.s, dim=1)


class CosFace(nn.Module):
    ...
    def forward(self, input, label):
        ...
        if not self.training:
            # For inference
            return F.softmax(cosine * self.s, dim=1)
            

class SphereFace(nn.Module):
    ...
    def forward(self, input, label):
        ...
        if not self.training:
            # For inference
            return F.softmax(cos_theta * NormOfFeature.view(-1, 1), dim=1)

Ở bước này, nhóm mình thu được 9 models khác nhau đến từ tổ hợp của các head-backbone init. và head architectures (Arc/Cos/Sphere) nêu trên.

2. Two-layer MLP

Nhằm tăng độ đa dạng của final ensemble, bọn mình tự build và train thêm 1 network nhỏ nữa bằng Keras. Input cho model này là feature vector lấy được từ việc concatenate 3 cái embeddings khác nhau, cung cấp bởi repo. insightface. Train dataset sẽ được chia ra làm 5 folds, ở mỗi fold, model tốt nhất sẽ được lưu lại bằng cách theo dõi validation loss. Trong quá trình forward, input feature và classifier weight đều được l2 normalized tương tự như trên. Ở bước này, nhóm mình có thêm được 5 models nữa.

3. Pseudo-labeling

Ensemble của 14 models từ bước 1 và 2 đạt được kết quả là 0.93933 trên bảng public. Nhóm mình sử dụng luôn ensemble này để pseudo-label cho tập test. Để tránh thêm quá nhiều noise vào data thì trong mỗi class, chỉ có 2 hình với predicted probability cao nhất được lựa chọn để thêm vào tập train. Tập train mới lúc này sẽ có ~ 6700 tấm. Sau đó, nhóm mình re-train lại tất cả models với tập train mới. Pseudo-labeling tăng kết quả trên bảng public lên 0.94102.

4. Xử lý class 1000 trong tập test

Nhóm mình đã thử khá nhiều cách khác nhau nhằm giải quyết vấn đề này nhưng chỉ có cách tune threshold là cho kết quả ổn nhất. Với những hình có top 1 predicted probablity nhỏ hơn threshold, predicted label thứ 5 được removed, label 1000 sẽ được thay thế vào ở vị trí số 1. Trong 2 tiếng cuối, nhóm mình đã spam bảng xếp hạng public để thử nhiều con số threshold khác nhau :)). Với threshold=0.18 (chọn đại ngày sinh của 1 thành viên trong nhóm), nhóm mình kết thúc với score 0.94346 xD.


Tổng kết cuộc thi 'Nhận diện người nổi tiếng' trên AIviVN
#2

dù đọc ko hiểu gì hết nhưng cảm ơn bạn đã chia sẻ, mãi yêu :*


#3

Xin và cám ơn đã, để dành sau nì có thể xài :stuck_out_tongue: