結果與討論
綜合之前的實驗,我們得到了一個效果不錯的模型。這個模型在我們的測試集上取得了 90% 以上的準確率,並且在實際應用中也取得了不錯的效果。
這裡我們將討論一些我們在訓練過程中的一些心得和經驗。
-
你可能會考慮要用什麼 Margin loss,可能是 CosFace 或是 ArcFace。但不管用什麼,請一定要搭配 PartialFC,訓練速度大幅提高,收斂結果穩定,且效能更好。
-
對於文本圖像的種類,一開始我們使用了約 500 種,後來增加到 800 種、10000 種等,最後決定納入 indoor dataset 作為基底,把整體的分類種類增加到約 40 萬種。這裡的結論和人臉辨識的任務一致:模型的效果和訓練資料的多樣性有很大的關係,因此我們需要使用大量的資料集,以確保模型能夠學習到足夠的特徵,並且能夠有效地區分不同的類別。
-
經實驗發現,採用低精度訓練可增強模型的泛化能力。我們認為這是因為模型極易發生過度擬合,而低精度訓練有助於減緩此問題。直接在
trainer
上設置低精度訓練並不可行,原因是部分運算子在 CUDA 上不支持此設定。因此,我們採用了torch.set_float32_matmul_precision('medium')
方法來實現低精度訓練。 -
經過實驗,在文本圖像分類的任務中,採用 LayerNorm 比 BatchNorm 效果更好,我們認為是因為文本圖像(如街道標誌、文件圖像等)通常包含著高度變異性的特徵,如不同字體、大小、背景雜訊等。LayerNorm 通過對每個樣本進行獨立標準化,幫助模型更有效地處理這些變異。而在人臉辨識中,使用 BatchNorm 有助於模型學習如何從高度相似的臉部圖像中辨識出細微的差異。這對於確保模型在各種不同條件(如照明、角度、表情變化等)下都能有效地辨識臉部特徵。
-
我們在單獨使用 CosFace 和 ArcFace 的時候,發現 ArcFace 的效果比較好;但是搭配了 PartialFC 之後情況截然不同,反而是 CosFace 效果更好。
-
Pretrain 是必要的,我們嘗試過不使用 Pretrain,但效果非常差。其中原因可能是因為我們所提供的資料集的多樣性仍然不夠,因此需要使用 Pretrain 來幫助模型學習到更多的特徵。我們再次感謝 timm 所提供的模型,這些模型幫助我們節省了大量的時間和人力。
-
在 Backbone 與 Head 串接的過程中,使用
nn.Flatten
取得所有資訊並使用nn.Linear
整合到特徵編碼層效果是最好的!但是缺點是需要佔用大量的參數 —— 在輕量模型的場景中,增加 1MB 的模型大小都是一件令人髮指的事情。為此我們嘗試了兩個方向,其一:使用nn.GlobalAvgPool2d
取得所有資訊並使用nn.Linear
整合到特徵編碼層;其二:使用nn.Conv2d
先將通道數降維至原本的 1/4 ,這邊我們稱為 Squeeze,接著再使用nn.Flatten
搭配nn.Linear
整合到特徵編碼層。經過實驗,使用 Squeeze 的策略是對的。這個策略不僅能夠有效地減少模型大小,同時維持模型的效能。 -
引入 CLIP 的特徵是一個不錯的策略,這個策略不僅能夠提高模型的效能,同時也能夠提高模型的泛化能力。這個策略的核心是利用 CLIP 模型對我們的模型進行知識蒸餾,從而將 CLIP 模型的特徵引入到我們的模型中。這個策略的效果是非常好的,我們認為這是因為 CLIP 模型具有豐富的知識,能夠幫助我們的模型學習到更穩健的特徵表示。
-
在 LayerNorm 之後再加上一層 BatchNorm,是讓我們模型可以站上 90% 的關鍵。我們認為這是因為 LayerNorm 和 BatchNorm 兩者的特性互補,LayerNorm 有助於模型學習到更穩定的特徵,而 BatchNorm 則有助於模型學習到跨樣本的特徵表示。