简体   繁体   English

具有多个输出并使用add_loss的自定义损失函数

[英]custom loss function with multiple output and using add_loss

I have an autoencoder in keras and I need a loss function which is the combination of mse, a binary_crossentropy and third part that tries to make minimum the number of pixels of output that have a value different from 0 or 1. the final loss should be like this: a mse+b binary_crossentropy+c*L. 我在keras中有一个自动编码器,我需要一个损失函数,该函数是mse,binary_crossentropy和第三部分的结合,第三部分试图使输出像素的数量最少(其值不同于0或1)。最终损失应为像这样:一个mse + b binary_crossentropy + c * L。 I used the below code for this but it produces this error: 我为此使用了以下代码,但会产生此错误:

Traceback (most recent call last): File "", line 134, in if (pred_w(i,j)>=0 & pred_w(i,j)<0.1)|(pred_w(i,j)<=1 & pred_w(i,j)>=0.9): TypeError: 'Tensor' object is not callable 追溯(最近一次呼叫最近):文件“”,第134行,如果(pred_w(i,j)> = 0&pred_w(i,j)<0.1)|(pred_w(i,j)<= 1&pred_w (i,j)> = 0.9):TypeError:'Tensor'对象不可调用

could you please tell me what should I do to solve this problem? 您能告诉我如何解决此问题吗? I appreciate your help. 我感谢您的帮助。

wtm=Input((4,4,1))
image = Input((28, 28, 1))
conv1 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl1e')(image)
conv2 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl2e')(conv1)
conv3 = Conv2D(64, (5, 5), activation='relu', padding='same', name='convl3e')(conv2)
#conv3 = Conv2D(8, (3, 3), activation='relu', padding='same', name='convl3e', kernel_initializer='Orthogonal',bias_initializer='glorot_uniform')(conv2)
BN=BatchNormalization()(conv3)
encoded =  Conv2D(1, (5, 5), activation='relu', padding='same',name='encoded_I')(BN)

#-----------------------adding w---------------------------------------   

wpad=Kr.layers.Lambda(lambda xy: xy[0] + Kr.backend.spatial_2d_padding(xy[1], padding=((0, 24), (0, 24))))
encoded_merged=wpad([encoded,wtm])

#-----------------------decoder------------------------------------------------
#------------------------------------------------------------------------------
deconv1 = Conv2D(64, (5, 5), activation='elu', padding='same', name='convl1d')(encoded_merged)
deconv2 = Conv2D(64, (5, 5), activation='elu', padding='same', name='convl2d')(deconv1)
deconv3 = Conv2D(64, (5, 5), activation='elu',padding='same', name='convl3d')(deconv2)
deconv4 = Conv2D(64, (5, 5), activation='elu',padding='same', name='convl4d')(deconv3)
BNd=BatchNormalization()(deconv4)

decoded = Conv2D(1, (5, 5), activation='sigmoid', padding='same', name='decoder_output')(BNd)    
model=Model(inputs=[image,wtm],outputs=decoded)

decoded_noise = GaussianNoise(0.5)(decoded)

#----------------------w extraction------------------------------------
convw1 = Conv2D(64, (5,5), activation='relu', name='conl1w')(decoded_noise)#24
convw2 = Conv2D(64, (5,5), activation='relu', name='convl2w')(convw1)#20
convw3 = Conv2D(64, (5,5), activation='relu' ,name='conl3w')(convw2)#16
convw4 = Conv2D(64, (5,5), activation='relu' ,name='conl4w')(convw3)#12
convw5 = Conv2D(64, (5,5), activation='relu', name='conl5w')(convw4)#8
convw6 = Conv2D(64, (5,5), activation='relu', name='conl6w')(convw5)#4
convw7 = Conv2D(64, (5,5), activation='relu',padding='same', name='conl7w',dilation_rate=(2,2))(convw6)#4
convw8 = Conv2D(64, (5,5), activation='relu', padding='same',name='conl8w',dilation_rate=(2,2))(convw7)#4
convw9 = Conv2D(64, (5,5), activation='relu',padding='same', name='conl9w',dilation_rate=(2,2))(convw8)#4
convw10 = Conv2D(64, (5,5), activation='relu',padding='same', name='conl10w',dilation_rate=(2,2))(convw9)#4
BNed=BatchNormalization()(convw10)
pred_w = Conv2D(1, (1, 1), activation='sigmoid', padding='same', name='reconstructed_W',dilation_rate=(2,2))(BNed)  

w_extraction=Model(inputs=[image,wtm],outputs=[decoded,pred_w])

count=0
for i in range(28):
    for j in range(28):
        if (pred_w(i,j)>=0 & pred_w(i,j)<0.1)|(pred_w(i,j)<=1 & pred_w(i,j)>=0.9):
            count+=1

loss = K.sum(0.7*mse(decoded, image),binary_crossentropy(pred_w,wtm))+count
w_extraction.add_loss(loss)

Technically the error just tells you that pred_w(i,j) should be pred_w[i,j] if you want to refer to an entry of the matrix. 从技术上讲,该错误仅告诉您如果要引用矩阵的条目,则pred_w(i,j)应该为pred_w [i,j]。 However, to make this code as you intend it to run requires quite a bit more rewrite. 但是,要按预期运行该代码,则需要进行大量重写。

To actually optimize a loss the main thing would be that it needs to be differentiable with regard to the weights in the networks. 为了实际优化损耗,主要的问题是它需要在网络权重方面是可区分的。 Examples you could use in this case could be: 在这种情况下可以使用的示例可能是:

  • (x-0.5)^N for a relatively high N (x-0.5)^ N表示相对较高的N

  • or log-barriers, ie -log(x)-log(1-x) 或日志屏障,即-log(x)-log(1-x)

actually counting the numbers (which will not help for optimization) could be achieved with something like 实际计数的数字(这对优化没有帮助)可以通过以下方式实现

count = tf.sum(pred_w<=0.1) + tf.sum(predictions_w>=0.9)

Maybe this is helpful to output how many numbers are in that range during training or something like this. 也许这有助于输出训练过程中该范围内的数字或类似数字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM