主要對下面這段代碼進行一下詳細的分析吧
# We use the stable formula: max(x, 0) - x * z + log(1 + exp(-abs(x)))
loss = F.relu(pred) - pred * label + F.Activation(-F.abs(pred), act_type='softrelu')
可能有會疑惑,這不像是交叉熵的公式。這個式子只是對原式loss = -(label * log(sigmoid(pred)) - (1-label)*log(1-sigmoid(x))的一種變換,但變化後的loss更加具有穩定性。
對原式loss = -(label * log(sigmoid(pred)) - (1-label)*log(1-sigmoid(x))展開,x=pred,z=label:
loss = -z * log( sigmoid(x) ) - (1-z) * log(1 - sigmoid(x))
= -z * log(1 / (1 + e^(-x))) - (1-z) * log ( 1 - 1 / (1 + e^(-x)))
= -z * (-log(1+e^(-x))) - (1 - z) * (log(e^(-x)) - log(1 + e^(-x)))
= z * log (1 + e^(-x)) - (1 - z) * (-x - log(1+e^(-x)))
= z * (-x) + x + log (1 + e^(-x))
但這裏還是和代碼中的loss部分看上去不太相同,原因在於爲了保持loss的穩定性,對它做了一點小小的變動。
對於z * (-x) + x + log (1 + e^(-x))
當x>0時,0<e^(-x)<1,數值穩定
當x<0時,e^(-x)隨着x的減小而增大趨向於正無窮,導致數值不夠穩定
但log (1 + e^(-|x|))就不存在數值不穩定的現象,所以可以對z * (-x) + x + log (1 + e^(-x))進行一點變動使它既能保持數值上的穩定,還和原式等價。
當x>0時:
z * (-x) + x + log (1 + e^(-x)) = z * (-x) + x + log (1 + e^(-|x|))
首先有等式:
x + log (1 + e^(-x)) = log(1 + e^(x))
當x<0時(x = -|x|):
z * (-x) + x + log (1 + e^(-x)) = z * (-x) + 0 + log (1 + e^(-|x|))
所以loss = z * (-x) + x + log (1 + e^(-x))與loss = max(x, 0) - x * z + log(1 + exp(-abs(x)))是等價的
注:
loss = max(x, 0) - x * z + log(1 + exp(-abs(x)))
其中max(x,0)就等價於x>0,中的x項及x<0中的0項。
max(x,0)寫成代碼就是F.relu(x),
log (1 + e^(-|x|))就是F.Activation(-F.abs(pred), act_type='softrelu')