tensorflow - 我的印象是,当模型调用损失函数时,Y_TRUE 和 Y_PRED 的最后一个维度会被丢弃
问题描述
我正在使用 Keras 和 tensorflow 上的“yolo”方法构建用于对象分类和定位的深度学习模型。我对单个输入图像的输出是 52*52*10 矩阵。因此,当我运行 model.summary() 时,我得到以下输出维度:
...
...
leaky_103 (LeakyReLU) (None, 52, 52, 128) 0 bnorm_103[0][0]
__________________________________________________________________________________________________
conv_104 (Conv2D) (None, 52, 52, 256) 294912 leaky_103[0][0]
__________________________________________________________________________________________________
bnorm_104 (BatchNormalization) (None, 52, 52, 256) 1024 conv_104[0][0]
__________________________________________________________________________________________________
leaky_104 (LeakyReLU) (None, 52, 52, 256) 0 bnorm_104[0][0]
__________________________________________________________________________________________________
conv_105 (Conv2D) (None, 52, 52, 10) 2570 leaky_104[0][0]
__________________________________________________________________________________________________
activation_2 (Activation) (None, 52, 52, 10) 0 conv_105[0][0]
==================================================================================================
Total params: 55,642,218
Trainable params: 55,592,682
Non-trainable params: 49,536
______________________________________________________________
即输出为 [None, 52, 52, 10]
所以,因为我必须为我的输出创建一个自定义损失函数(因为我必须在切片上应用交叉熵并在[:,:,0:2]
切片上应用另一个损失[:,:,2:6]
)。下面是损失函数的摘录
epsilon = 0.000001
def loss(y_true, y_pred):
loss1 = K.mean(K.sum(K.categorical_crossentropy(y_true[:,:,:,0:2], y_pred[:,:,:,0:2]),
axis = (1,2,3)),
axis = 0)
loss2 = K.mean(K.sum(-K.log(K.abs(tf.math.subtract(y_true[:,:,:,2:6],
y_pred[:,:,:,2:6]))
+ epsilon),
axis = (1,2, 3)),
axis = 0)
return loss1+loss2
但是在运行时model.compile()
,我收到以下错误:
ValueError: 3 维输入的无效缩减维数 3。对于 'loss_6/activation_2_loss/Sum_2' (op: 'Sum'),输入形状:[?,52,52], [3] 和计算的输入张量:input[1] = <1 2 3>。
我解释说,实际上,在调用损失函数时,损失是沿着最后一个维度逐层计算的,并减少了损失函数中的轴维度,“修改后的损失函数”是:
ε = 0.000001
def loss(y_true, y_pred):
loss1 = K.mean(K.sum(K.categorical_crossentropy(y_true[:,:,:,0:2], y_pred[:,:,:,0:2]),
axis = (1,2)),
axis = 0)
loss2 = K.mean(K.sum(-K.log(K.abs(tf.math.subtract(y_true[:,:,:,2:6],y_pred[:,:,:,2:6])) + epsilon), axis = (1,2)), axis = 0)
return loss1+loss2
在此之后模型编译成功。谁能告诉我天气我对我的假设是对还是错。
解决方案
你是对的:categorical_crossentropy
,将减少最后一个轴(维度 3)。您对 3 个班级有“一次”损失,而不是每个班级都有一次损失。
所以你输入(batch, 52, 52, 3)
它会返回(batch, 52, 52)
。因此,您sum
只能在维度 1 和 2 上工作,没有维度 3。
你相应地更正了loss1
。
关于loss2
,您忘记添加总和的维度。所以它将处于不同的数量级,因为在轴 0 中有一个,而在轴 0 中loss1
有一个。mean
loss2
sum
你需要loss2
像以前一样:
loss2 = K.mean(K.sum(-K.log(K.abs(tf.math.subtract(y_true[:,:,:,2:6],
y_pred[:,:,:,2:6]))
+ epsilon),
axis = (1,2, 3)),
axis = 0)
我不是专门从事这项任务的,但也许你在那里仍然有不同的数量级,因为categorical_crossentropy
在轴 3 上执行平均值,所以你loss2
可能还需要这个平均值:
loss2 = K.mean(K.sum(-K.log(K.abs(y_true[:,:,:,2:6] - y_pred[:,:,:,2:6]) + epsilon),
axis=(1,2))) #let axis 3 to the mean.
提示:mean
在轴 0 上是可选的。Keras 稍后会为您完成。保持维度 0 不变的优点是以后可以使用样本权重。
提示2:tf.math.subtract(a, b)
等于写作a-b
。
推荐阅读
- java - DES蛮力(学术)
- xrp - Ripple XRP Ledger - 如何创建资产或代币?实现这一目标的交易类型是什么?
- c++ - 无法理解以下代码是如何工作的
- optimization - docplex - 将 interval_var 的大小设置为另一个变量的函数
- java - Forge 1.12.2 Coremodding:java.lang.ClassCircularityError
- html - 如何动态地将 select 和 ng-select 重置为第一个选项
- selenium - Selenium Web Driver 自动化 PaleMoon Web 浏览器?
- android - 为什么我的 TextField 在模拟器中被清除,但在我的 Galaxy 上却没有?
- c++ - 尝试通过对所有三个点应用相同的变换来制作一个可以旋转和移动的三角形
- c++ - 如何使用 VSCode 在 docker 中调试 C++ 应用程序