解析ArcFace源码
貓貓與橙子 2019-10-09 17:20:38 ?893 ?收藏 2
展開
論文分享,代碼復現
主要用于論文翻譯分享,代碼復現,結合場景數據,提升實際模型性能
貓貓與橙子
¥19.90
分享賺¥1.99 訂閱專欄
最近在看arcFace當中pytorch代碼的實現,先把InsightFace中ArcFace代碼貼出來:?
class Arcface(Module):
? ? # implementation of additive margin softmax loss in https://arxiv.org/abs/1801.05599 ? ?
? ? def __init__(self, embedding_size=512, classnum=51332, ?s=64., m = 0.5):
? ? ? ? super(Arcface, self).__init__()
? ? ? ? self.classnum = classnum
? ? ? ? self.kernel = Parameter(torch.Tensor(embedding_size, classnum))
? ? ? ? # initial kernel
? ? ? ? self.kernel.data.uniform_(-1, 1).renorm_(2, 1, 1e-5).mul_(1e5) #uniform_(-1, 1)服從均勻分布,mul_對應點相乘
? ? ? ? self.m = m # the margin value, default is 0.5
? ? ? ? self.s = s # scalar value default is 64, see normface https://arxiv.org/abs/1704.06369
? ? ? ? self.cos_m = math.cos(m)
? ? ? ? self.sin_m = math.sin(m)
? ? ? ? self.mm = self.sin_m * m ?# issue 1
? ? ? ? self.threshold = math.cos(math.pi - m)
? ? def forward(self, embbedings, label):
? ? ? ? # weights norm
? ? ? ? nB = len(embbedings)
? ? ? ? kernel_norm = l2_norm(self.kernel, axis=0)
? ? ? ? # cos(theta+m)
? ? ? ? cos_theta = torch.mm(embbedings, kernel_norm)#進行矩陣乘法
# ? ? ? ? output = torch.mm(embbedings,kernel_norm)
? ? ? ? cos_theta = cos_theta.clamp(-1,1) # for numerical stability
? ? ? ? cos_theta_2 = torch.pow(cos_theta, 2)
? ? ? ? sin_theta_2 = 1 - cos_theta_2
? ? ? ? sin_theta = torch.sqrt(sin_theta_2)
? ? ? ? cos_theta_m = (cos_theta * self.cos_m - sin_theta * self.sin_m)
? ? ? ? # this condition controls the theta+m should in range [0, pi]
? ? ? ? # ? ? ?0<=theta+m<=pi
? ? ? ? # ? ? -m<=theta<=pi-m
? ? ? ? cond_v = cos_theta - self.threshold
? ? ? ? cond_mask = cond_v <= 0
? ? ? ? keep_val = (cos_theta - self.mm) # when theta not in [0,pi], use cosface instead
? ? ? ? cos_theta_m[cond_mask] = keep_val[cond_mask]
? ? ? ? output = cos_theta * 1.0 # a little bit hacky way to prevent in_place operation on cos_theta
? ? ? ? idx_ = torch.arange(0, nB, dtype=torch.long)
? ? ? ? output[idx_, label] = cos_theta_m[idx_, label]
? ? ? ? output *= self.s # scale up in order to make softmax work, first introduced in normface
? ? ? ? return output
對于torch中一些函數的理解
1)對于self.kernel = Parameter(torch.Tensor(embedding_size, classnum))中,Parameter的作用:
首先可以把Parameter理解為類型轉換函數,將一個不可訓練的類型Tensor轉換成可以訓練的類型parameter并將這個parameter綁定到這個module里面(net.parameter()中就有這個綁定的parameter,所以在參數優化的時候可以進行優化的),所以經過類型轉換這個self.kernel變成了模型的一部分,成為了模型中根據訓練可以改動的參數了。使用這個函數的目的也是想讓某些變量在學習的過程中不斷的修改其值以達到最優化。(摘自:原文鏈接:https://blog.csdn.net/qq_36955294/article/details/88117170)
看了torch官網的解釋:
"Variable的一種,常被用于模塊參數(module parameter)。
Parameters?是?Variable?的子類。Paramenters和Modules一起使用的時候會有一些特殊的屬性,即:當Paramenters賦值給Module的屬性的時候,他會自動的被加到?Module的 參數列表中(即:會出現在?parameters() 迭代器中)。將Varibale賦值給Module屬性則不會有這樣的影響。 這樣做的原因是:我們有時候會需要緩存一些臨時的狀態(state)"
這句話中,embedding_size = 512,classnum是人臉識別的ID數,先使用orch.Tensor,生成一個512×classnum的張量,然后通過Parameter將這個張量轉化為可以訓練的模型;
2)對于self.kernel.data.uniform_(-1, 1).renorm_(2, 1, 1e-5).mul_(1e5)??的理解:
#uniform_(from=-1, to=1) → Tensor????將tensor用從均勻分布中抽樣得到的值填充。
# renorm_返回一個張量,包含規范化后的各個子張量,使得沿著2維劃分的各子張量的1范數小于1e-5
# mul_用標量值1e5乘以輸入input的每個元素,并返回一個新的結果張量;
以上是對pytorch中一些函數的理解;
?
對于arcface公式的代碼實現
對于arcFace的實現實際應該是包括兩部分,第一部分是cosin函數部分;第二部分就是常規的softmax部分;
在pytorch代碼中,第二部分直接有函數實現,是可以直接使用的;所以重點是cosin函數部分的實現;
下面就重點講解記錄一下怎樣一步步的實現第一部分代碼:
1)對Feature進行了l2 norm,對參數也進行了l2 norm.所以權值參數×feature = cos theta
2)將cos theta夾逼到【-1, 1】之間,因為cos theta的定義域在【0,pi】值域實在【-1,1】之間;
3)計算cos(theta + m)使用到余弦定理;
4)計算完成后,要判斷theta是否超出范圍,進行數據調整,這一塊的判讀原理在下圖:
(不知道這樣理解是否有錯?望大佬賜教)
判斷后得出一個值為0或1的mask,通過使用cos_theta_m[cond_mask] = keep_val[cond_mask],將超出范圍的值使用keep_val表示,加入[cond_mask],是將mask為1(True)位置的元素取出,進行修改;
————————————————
版權聲明:本文為CSDN博主「貓貓與橙子」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_22764813/article/details/101437898
總結
以上是生活随笔為你收集整理的解析ArcFace源码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一分钟理解softmax函数(超简单)
- 下一篇: insightface和facenet效