我有一个带有输出的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)。