我有一个带有输出的CNN
[[a,b,c,d,e],[a1,b1,c1,d1,e1]...]
然而,“a”代表某个东西在盒子中的得分,而其他值代表其他内容的得分。
我希望“a”使用例如二元交叉熵计算,而其他值使用均方误差计算
在标签中,“a”要么是1(其他值非零),要么是0(所有其他值也为零)
所以我希望输出中的“a”在0到1之间。
我尝试创建自己的损失函数:
def custom_loss(y_true,y_pred): return K.mean(K.binary_crossentropy(y_true[0], y_pred[0]), axis=-1) + K.mean(K.square(y_pred[1:] - y_true[1:]), axis=-1)
然而,它抛出了一个相当严重的错误,以下部分提供了最多的信息(我认为):
InvalidArgumentError (see above for traceback): Incompatible shapes: [4] vs. [5] [[Node: loss/predictions_loss/mul = Mul[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/device:GPU:0"](loss/predictions_loss/Mean_2, _arg_predictions_sample_weights_0_2/_1191)]] [[Node: loss/mul/_1305 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/device:CPU:0", send_device="/job:localhost/replica:0/task:0/device:GPU:0", send_device_incarnation=1, tensor_name="edge_12439_loss/mul", tensor_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]
这可能是什么原因造成的?形状4与5不兼容,这很奇怪,因为我的输出和输入具有相同的形状。
有没有办法修复或解决这个问题?
感谢帮助。
回答:
我假设你的输出形状是(samples, boxes, 5)
。
解决方案
def custom_loss(y_true,y_pred): cross = K.mean(K.binary_crossentropy(y_true[:,:,:1], y_pred[:,:,:1]), axis=-1) mse = K.mean(K.square(y_pred[:,:,1:] - y_true[:,:,1:]), axis=-1) return cross + mse
如果由于cross
和mse
形状不同而仍然出现不兼容问题,你可能需要进一步使用K.mean()
,直到两者的形状保持为(samples, boxes)
或仅(samples,)
。
如果你不打算使用任何样本加权,你可以从均值中移除axis=-1
。
错误的维度
不要忘记张量的第一个维度是样本,因此你需要从最后一个维度中提取a
(因为第二个维度是“boxes”):
y_true[:,:,:1]
的形状为(samples, boxes, 1)
y_true[:,:,1:]
的形状为(samples, boxes, 4)
我使用:1
来保持最后一个维度,如果你只使用0
,形状将变为(samples, boxes)
。