我使用Keras为YOLO实现了自定义损失函数和模型。我正在使用Tensorflow作为后端。
import pickle
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from keras.models import Sequential,load_model
from keras.layers import Dense,Conv2D,Activation,MaxPooling2D,Flatten
import keras as k
from keras import optimizers
import cv2
batch=12
sess= tf.Session()
#loss function
def yolo_loss(yTrue,yPred):
coord=5
noobj=0.5
L_noobj=1
L_obj=1
if yTrue[6] == 1:
L_obj=0
if yTrue[5] == 1:
L_noobj=0
w=coord*L_obj*(tf.square([tf.sqrt(yTrue[2])-tf.sqrt(yPred[2])]))
h=coord*L_obj*(tf.square([yTrue[3]-yPred[3]]))
x=coord*L_obj*(tf.square([yTrue[0]-yPred[0]]))
y=coord*L_obj*(tf.square([yTrue[1]-yPred[1]]))
no_obj=noobj*L_noobj*(tf.square([yTrue[6]-yPred[6]]))
obj=L_obj*(tf.square([yTrue[5]-yPred[5]]))
clss=L_obj*(tf.square([yTrue[4]-yPred[4]]))
loss=w+h+x+y+no_obj+obj+clss
return loss
def custom_loss(yTrue,yPred):
loss=None
for a in range(batch):
loss_per_sample=0
for b in range(4):
for c in range(4):
loss_per_sample += yolo_loss(yTrue[a,b,c,0:],yPred[a,b,c,0:])
if loss == None:
loss=tf.stack(loss_per_sample)
else:
x=tf.stack(loss_per_sample)
loss=tf.concat([loss,x],0)
loss=tf.reshape(loss,[-1,1])
return loss
#load data and labels
x_train=pickle.load(open('data_image.pickle','rb'))
y_train=pickle.load(open('data_label.pickle','rb'))
test=pickle.load(open('test_image.pickle','rb'))
# model
model=Sequential()
model.add(Conv2D(16,(7,7),input_shape=x_train.shape[1:],padding="same"))
model.add(Activation("relu"))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(32,(3,3),padding="same"))
model.add(Activation("relu"))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(64,(3,3),padding="same"))
model.add(Activation("relu"))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(128,(3,3),padding="same"))
model.add(Activation("relu"))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(512,(3,3),padding="same"))
model.add(Activation("relu"))
model.add(MaxPooling2D((2,2)))
model.add(Conv2D(512,(3,3),padding="same"))
model.add(Activation("relu"))
model.add(Conv2D(1024,(3,3),padding="same"))
model.add(Activation("relu"))
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"])
model.fit(x_train,y_train,batch_size=batch,epochs=100)
model.save('yolo.model')
当我训练模型时,损失值将变为NAN。但是在自定义损失函数的“ W”和“ h”中删除tf.sqrt()之后,损失几乎为零。但是问题是边界框的“ W”和“ h”值始终为零。我认为tf.sqrt()函数中有一些东西。请有人能告诉我这是怎么回事。
答案 0 :(得分:0)
我认为这是一种除以零误差的问题,我在使用Yolo和darkflow进行玩家检测时遇到了这个问题,我要解决的一件事是对批量大小和学习率进行了一些调整。
答案 1 :(得分:0)
您在最后一层使用relu
,这是不期望的。这可能会导致梯度消失。
此外,在使用sqrt函数之前,请做一些检查,例如负值。
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"])