我目前正在尝试使用二进制结果实现自定义丢失函数(精度),但Tensorflow后端拒绝使用循环函数,这必须用于生成' 0'或者' 1'。
据我所研究,这是因为Tensorflow将该轮的渐变定义为None,而损失函数不能返回None。
我目前已实施此自定义损失,以尽可能接近创建' 0'或者' 1'在R Keras界面。
precision_loss<-function(y_true,y_pred){
y_pred_pos = K$clip(y_pred, 0, 1)
#Custom sigmoid to generate '0' '1'
y_pred_pos = K$maximum(0,K$minimum(1,(y_pred_pos+0.0625)/0.125))
y_pred_neg = 1 - y_pred_pos
y_pos = K$clip(y_true, 0, 1)
#Custom sigmoid to generate '0' '1'
y_pos = K$maximum(0,K$minimum(1,(y_pos+0.0625)/0.125))
y_neg = 1 - y_pos
#Generate confusion matrix counts
tp = K$sum(y_pos*y_pred_pos)
tn = K$sum(y_neg*y_pred_neg)
fp = K$sum(y_neg*y_pred_pos)
fn = K$sum(y_pos*y_pred_neg)
return(1-(tp/(tp+fp+K$epsilon())))
}
注意&#34; sigmoid&#34; :K $最大值(0,K $最小值(1,(y_pos + 0.0625)/0.125))
我想要实现的是这个解决方法:
precision_loss<-function(y_true, y_pred){
y_pred_pos = K$round(K$clip(y_pred, 0, 1))
y_pred_neg = 1 - y_pred_pos
y_pos = K$round(K$clip(y_true, 0, 1))
y_neg = 1 - y_pos
#Generate confusion matrix counts
tp = K$sum(K$clip(y_pos * y_pred_pos,0,1))
tn = K$sum(K$clip(y_neg * y_pred_neg,0,1))
fp = K$sum(K$clip(y_neg * y_pred_pos,0,1))
fn = K$sum(K$clip(y_pos * y_pred_neg,0,1))
return(1-(tp/(tp+fp+K$epsilon())))
}
有些人在没有使用round来生成损失函数中的二进制结果的情况下有另一种实现吗?
PD:在自定义指标功能中,允许回合
答案 0 :(得分:1)
为了构建二进制损失函数,仅仅构建自定义损失函数是不够的。您还必须预先定义渐变。
对于某些点,您的高维损失函数将为零,对于所有其他点,您的高维损失函数将为零。对于此空间中的所有非连续点,分析计算渐变是不可能的(即这些点甚至不存在渐变的概念),因此您只需要定义一。对于此空间中的所有连续点(例如,所有损失值均为1的开放集),梯度将存在,但它将为零,因此您还必须预先定义渐变值,否则你的重量根本不会移动。
这意味着无论哪种方式,您都必须定义自己的自定义“渐变”计算函数,以替换图中特定节点(损失函数节点)的Keras'(即TensorFlow)自动微分引擎。
你当然可以通过修改Keras或TensorFlow的本地副本来实现这一目标,但没有任何好处可以来自它。
此外,即使你设法做到这一点,考虑一下:如果你的损失函数只返回0或1,这意味着它只能区分两种状态:模型的预测是100%正确(0损失)或它不是100%正确(1损失)。对于所有非100%的情况,梯度的大小必须相同。这是一个理想的财产吗?
你的准二元sigmoid解决方案也存在同样的问题:几乎所有地方的渐变几乎都是零,并且在几乎不会几乎为零的几个点上,它几乎是无穷大的。如果您尝试使用该损失函数训练模型,它将不会学到任何东西。
答案 1 :(得分:1)
正如您所注意到自定义丢失函数需要基于已定义渐变的函数(为了最小化损失函数),这是对于简单的指标不是必需的。某些函数如“round”和“sign”很难在损失函数中使用,因为它们的渐变始终为null或无穷大,这对最小化没有帮助。这可能是为什么他们的渐变未定义,默认情况下。
然后,您有两个选择:
您选择了选项2,这是我认为的最佳选择。但是你的“sigmoid”非常线性,所以可能不是你的“圆形”函数的一个很好的近似值。您可以使用由于使用指数而变慢的实际sigmoid,但是您可以使用修改的softsign获得类似的结果:
max_gradient = 100
K $最大值(0,K $最小值(1,0.5 *(1+(max_gradient * y_pos)/(1+ max_gradient * abs(y_pos)))))
max_gradient系数可用于使您的边缘更加清晰,大约0.5。它将最大梯度定义为0.5。