Description
I had tried to repeat the train code, just for the network with one class object detection. So I saved the structure of train.py and model.py, except the creation of Yolo network - I built it layer by layer. But, when I've tried to start yolo training, I got the warning: "WARNING:tensorflow:Gradients do not exist for variables ['Layer_Conv_81/kernel:0', 'Layer_Conv_91/kernel:0', 'Layer_Batch_81/gamma:0', 'Layer_Batch_81/beta:0', 'Layer_Batch_91/gamma:0', 'Layer_Batch_91/beta:0', 'Output_1/kernel:0', 'Output_2/kernel:0'] when minimizing the loss. If you're using model.compile()
, did you forget to provide a loss
argument?". I suppose, that this must be caused in definition of loss argument i.e
trainModel.compile(optimizer=Adam(lr=1e-3), loss={'GetLoss': lambda y_train, y_pred: y_pred}, run_eagerly=True)
- lambda function in loss returns y_pred, and Keras could not connect loss result of Lambda layer (which combines yolo outputs and true ground inputs) with yolo output layers. But original train script had not produce such warning. I'm new to Keras, so can anybody say, what can invoke gradient warning? For convinience, I place a part of my code below:
def MakeYoloMainStructure():
inputImage = Input(shape=(IMAGE_SIDES[0], IMAGE_SIDES[1], 3), name='Main_Input')
# Start placing layers
layer1_1 = Conv2D(32, (3,3), strides=(1,1), use_bias=False, padding='same', name='Layer_Conv_1')(inputImage)
...
layer80_3 = LeakyReLU(alpha=alp, name='Layer_Leaky_80')(layer80_2)
layer81_1 = Conv2D(1024, (3,3), strides=(1,1), use_bias=False, padding='same', name='Layer_Conv_81')(layer80_3) # From this layer we make fork for first output (!)
layer81_2 = BatchNormalization(epsilon=eps, name='Layer_Batch_81')(layer81_1)
layer81_3 = LeakyReLU(alpha=alp, name='Layer_Leaky_81')(layer81_2)
layer82_1 = Conv2D(3*6, (1,1), strides=(1,1), use_bias=False, padding='same', name='Output_1')(layer81_3) # FIRST output layer (!)
layer84_1 = layer80_3
layer85_1 = Conv2D(256, (1,1), strides=(1,1), use_bias=False, padding='same', name='Layer_Conv_83')(layer84_1)
...
layer106_1 = Conv2D(3*6, (1,1), strides=(1,1), use_bias=False, padding='same', name='Output_3')(layer105_3) # THIRD output layer (!)
# Net structure is completed
yoloBoneModel = Model(inputImage, [layer82_1, layer94_1, layer106_1])
return yoloBoneModel
def MakeYoloTrainStructure(yoloBoneMode):
gridInput_all = [Input(shape=(GRID_SIDES[1], GRID_SIDES[1], 3, 6), name='Grid_Input_1'), Input(shape=(GRID_SIDES[2], GRID_SIDES[2], 3, 6), name='Grid_Input_2'), Input(shape=(GRID_SIDES[3], GRID_SIDES[3], 3, 6), name='Grid_Input_3')]
layer_loss = Lambda(GetLoss, output_shape=(1,), name='GetLoss', arguments={'threshold': thresh})([*yoloBoneModel.output, *gridInput_all])
yoloTrainModel = Model([yoloBoneModel.input, *gridInput_all], layer_loss)
return yoloTrainModel
def GetLoss(args, threshold=0.5):
modelOutputs = args[:3]
checkInputs = args[3:]
# ......
# Numerous manipulations to get loss of objects detection
# ......
return loss
def main():
boneModel = MakeYoloMainStructure()
trainModel = MakeYoloTrainStructure(boneModel)
trainModel.compile(optimizer=Adam(lr=1e-3), loss={'GetLoss': lambda gridInput_all, y_pred: y_pred}, run_eagerly=True)
batchSize = 32
trainModel.fit(GetDataGenerator(batchSize), steps_per_epoch=2000//batchSize, epochs=50, initial_epoch=0)