【问题标题】:Tensorflow custom loss function NaNs during training训练期间的Tensorflow自定义损失函数NaNs
【发布时间】: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


    【解决方案1】:

    您似乎仍在使用nan 值计算您的损失,尽管您正试图避免它。也许尝试这样的事情:

    binary_loss_func = tf.keras.losses.BinaryCrossentropy()
    def loss_func(true_labels, pred_labels):
        true_labels = tf.where(tf.math.is_nan(true_labels), tf.zeros_like(true_labels), true_labels)
        condition = tf.equal(true_labels, 0.0)
    
        binary_loss = tf.where(condition, tf.reduce_mean(true_labels), binary_loss_func(true_labels[:,0], pred_labels[:, 0]))
    
        mse_loss1 = tf.reduce_mean(tf.where(tf.equal(true_labels[:, 1:3], 0.0), true_labels[:, 1:3],
                                            tf.square(tf.subtract(true_labels[:, 1:3], pred_labels[:, 1:3])))) 
    
        mse_loss2 = tf.reduce_mean(tf.where(tf.equal(true_labels[:, 4:], 0.0), true_labels[:, 4:], 
                                            tf.square(tf.subtract(true_labels[:, 4:], pred_labels[:, 4:]))))
    
        angular_loss = tf.reduce_mean(tf.where(tf.equal(true_labels[:, 3], 0.0), 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
    

    【讨论】:

      猜你喜欢
      • 2021-12-27
      • 2016-02-23
      • 2021-02-21
      • 1970-01-01
      • 2021-02-24
      • 2017-08-24
      • 1970-01-01
      • 1970-01-01
      • 2020-11-25
      相关资源
      最近更新 更多