在使用yolo自定义损失函数训练神经网络中,损失等于nan吗?

时间:2020-04-22 22:37:03

标签: python keras neural-network computer-vision yolo

我制作了自定义的yolo损失函数,基本上与此处的https://github.com/Neerajj9/Text-Detection-using-Yolo-Algorithm-in-keras-tensorflow/blob/master/Yolo.ipynb

相同

在训练时,它显示出Nan的损失。为什么会这样?

def yolo_loss_function(y_true,y_pred):
    #y_true,y_pred:None,16,16,1,5
    l_coords = 5.0
    l_noob = 0.5
    coords = y_true[:,:,:,:,0]*l_coords
    noobs = (-1*(y_true[:,:,:,:,0]-1)*l_noob)
    p_pred = y_pred[:,:,:,:,0]  #probability that theer is text or not
    p_true = y_true[:,:,:,:,0]  #Always 1 or 0
    x_true = y_true[:,:,:,:,1]
    x_pred = y_pred[:,:,:,:,1]
    yy_true = y_true[:,:,:,:,2]
    yy_pred = y_pred[:,:,:,:,2]
    w_true = y_true[:,:,:,:,3]
    w_pred = y_pred[:,:,:,:,3]
    h_true = y_true[:,:,:,:,4]
    h_pred = y_pred[:,:,:,:,4]

    #We have different loss value depending on whether text is present or not
    p_loss_absent = K.sum(K.square(p_pred-p_true)*noobs)
    p_loss_present = K.sum(K.square(p_pred-p_true))

    x_loss = K.sum(K.square(x_pred-x_true)*coords)
    yy_loss = K.sum(K.square(yy_pred-yy_true)*coords)
    xy_loss = x_loss + yy_loss

    w_loss = K.sum(K.square(K.sqrt(w_pred)-K.sqrt(w_true))*coords)
    h_loss = K.sum(K.square(K.sqrt(h_pred)-K.sqrt(h_true))*coords)
    wh_loss = w_loss+h_loss

    loss = p_loss_present+p_loss_absent + xy_loss + wh_loss

    return loss

#optimizer
opt = Adam(lr=0.0001,beta_1=0.9,beta_2=0.999,epsilon=1e-08,decay=0.0)

#checkpoint
checkpoint = ModelCheckpoint('model/text_detect.h5',monitor='val_loss',verbose =1,save_best_only=True,mode='min',period=1)

model.compile(loss=yolo_loss_function,optimizer=opt,metrics=['accuracy'])

我正在使用通过MobileNetV2架构进行的转移学习。

P.S。 -Loss goes to NAN when training the custom YOLO model如此,我尝试从损失函数中删除sqrt。那除去了nan,但我的损失并没有减少。它稳定地增加,然后保持恒定在大约6。上述职位的答案似乎无济于事,因为我在任何地方都看不到0的“划分”。

编辑:

def yolo_model(input_shape):


    inp = Input(input_shape)

    model = MobileNetV2( input_tensor= inp , include_top=False, weights='imagenet')
    last_layer = model.output

    conv = Conv2D(512,(3,3) , activation='relu' , padding='same')(last_layer)
    conv = Dropout(0.4)(conv)
    bn = BatchNormalization()(conv)
    lr = LeakyReLU(alpha=0.1)(bn)


    conv = Conv2D(128,(3,3) , activation='relu' , padding='same')(lr)
    conv = Dropout(0.4)(conv)
    bn = BatchNormalization()(conv)
    lr = LeakyReLU(alpha=0.1)(bn)


    conv = Conv2D(5,(3,3) , activation='sigmoid' , padding='same')(lr)

    final = Reshape((grid_h,grid_w,classes,info))(conv)

    model = Model(inp,final)

    return model

我正在上传模型。最后一个Conv2D层的激活是relu,我将其更改为sigmoid以响应一个答案。另外,我的图像从(-1,1)归一化。在第1个纪元后,我的程序显示loss:nan accuracy:1.0000,下面显示一行could not bring down loss from inf

1 个答案:

答案 0 :(得分:0)

您在最后一层使用relu,这是不期望的。这可能会导致梯度消失。

在原始的yolo纸中,坐标是有界的,这意味着坐标(高度,宽度)在(0,1)范围内进行了归一化。因此,也许摆脱relu并尝试线性或S型。

model.add(Conv2D(7,(3,3),padding="same"))
model.add(Activation("relu"))

adam = optimizers.adam(lr=0.001)
model.compile(loss=custom_loss,optimizer=adam,metrics=["accuracy"])