【发布时间】:2021-12-28 02:44:36
【问题描述】:
我正在尝试为检测对象并在其上绘制非轴对齐边界框的 CNN 编写自定义损失函数。我的输入是 200x200 图像,输出/标签是 6d 形式的向量
[object_present, x,y, angle, width, height]
其中object_present是表示对象是否存在的二进制特征,(x,y)是边界框的中心,角度是bbox从轴对齐开始的旋转角度,宽度和高度是bbox的尺寸。当 object_present = 0 时,所有其他特征都设置为 NaN。
因此,我的自定义损失函数需要忽略负样本的 NaN,并将二元交叉熵损失应用于 object_present 特征。对于正样本,我还必须包括 (x,y) 和宽度、高度的 MSE 损失,以及我定义为 arctan(sin(angle1 - angle2), cos(angle1-angle2)) 的角度回归损失。我的实现如下:
binary_loss_func = tf.keras.losses.BinaryCrossentropy()
def loss_func(true_labels, pred_labels):
binary_loss = binary_loss_func(true_labels[:,0], pred_labels[:, 0])
mse_loss1 = tf.reduce_mean(tf.where(tf.math.is_nan(true_labels[:,1:3]), tf.zeros_like(true_labels[:, 1:3]),
tf.square(tf.subtract(true_labels[:, 1:3], pred_labels[:, 1:3]))))
mse_loss2 = tf.reduce_mean(tf.where(tf.math.is_nan(true_labels[:,4:]),
tf.zeros_like(true_labels[:, 4:]), tf.square(tf.subtract(true_labels[:, 4:], pred_labels[:, 4:]))))
angular_loss = tf.reduce_mean(tf.where(is_nan(true_labels[:,3]), tf.zeros_like(true_labels[:, 3]),
tf.abs(tf.atan2(tf.sin(true_labels[:, 3] - pred_labels[:, 3]), tf.cos(true_labels[:, 3] - pred_labels[:, 3])))))
return mse_loss1 + mse_loss2 + binary_loss + angular_loss
我的问题是这会在第一批训练后返回 NaN 损失值(只有第一批不给出 NaN 损失),即使我认为上面的代码应该为负样本返回 0 损失。我已经确认 Binary Loss 函数正在返回应有的实数,所以问题在于损失的其他组成部分。在用 tf.print 语句进行了一些调试后,我发现 pred_labels 在第一批训练后变成了 NaN。我不确定为什么会发生这种情况,以及我的自定义损失函数的定义方式是否存在问题,或者我的模型是否存在问题。我使用的模型是:
IMAGE_SIZE = 200
CONV_PARAMS = {"kernel_size": 3, "use_bias": False, "padding": "same"}
CONV_PARAMS2 = {"kernel_size": 5, "use_bias": False, "padding": "same"}
model = Sequential()
model.add(
Reshape((IMAGE_SIZE, IMAGE_SIZE, 1), input_shape=(IMAGE_SIZE, IMAGE_SIZE))
)
model.add(Conv2D(16, **CONV_PARAMS))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPool2D())
model.add(Conv2D(32, **CONV_PARAMS))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPool2D())
model.add(Conv2D(64, **CONV_PARAMS))
model.add(BatchNormalization())
model.add(Activation('relu'))
model.add(MaxPool2D())
model.add(Flatten())
model.add(Dense(6))
【问题讨论】:
标签: python tensorflow keras nan