python - 具有多个输出并使用 add_loss 的自定义损失函数
问题描述
我在 keras 中有一个自动编码器,我需要一个损失函数,它是 mse、binary_crossentropy 和第三部分的组合,它试图使值不同于 0 或 1 的输出像素数最小。最终损失应该是像这样:a mse+b binary_crossentropy+c*L。我为此使用了以下代码,但它会产生此错误:
回溯(最后一次调用):文件“”,第 134 行,在 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
你能告诉我我该怎么做才能解决这个问题吗?我感谢您的帮助。
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)
解决方案
从技术上讲,如果您想引用矩阵的条目,错误只是告诉您 pred_w(i,j) 应该是 pred_w[i,j] 。但是,要使此代码按照您的预期运行,需要进行更多的重写。
要真正优化损失,主要的事情是它需要在网络中的权重方面是可微的。您可以在这种情况下使用的示例可能是:
(x-0.5)^N 表示相对较高的 N
或对数障碍,即-log(x)-log(1-x)
实际上计算数字(这对优化没有帮助)可以通过类似的方法来实现
count = tf.sum(pred_w<=0.1) + tf.sum(predictions_w>=0.9)
也许这有助于在训练期间输出该范围内的数字数量或类似情况。
推荐阅读
- r - 在极坐标图上绘制曲线
- android - 在 Android 上删除 SSL 固定
- django - 每个页面上的 ensure_csrf_cookie
- puppeteer - 检测渲染事件/布局更改(或任何知道页面何时停止“更改”的方式)
- amazon-s3 - Apache Drill 可以处理 KMS 加密文件吗?
- node.js - Node.js 从一个客户端获取数据并将其发送到另一个客户端
- actions-on-google - 我们可以从 API 创建一个谷歌助手操作而不是谷歌“gactions”CLI 吗?
- spring - UncategorizedKeyValueException 试图通过具有事务支持的存储库保存 RedisHash
- sql - 使用 SQL 根据值获取行和列?
- r - 平均神经网络 (avNNet) 是所有迭代的平均值吗?