Reputation: 61
I was going to write my own implementation of the YOLOv3 and coming up with some problem with the loss function. The original paper mention that he uses Binary Cross Entropy on the class prediction part, which is what I did.
I tried reading some code by the original darknet code, but I didn't find anything that that related to the BCE loss. And I read furthermore with some approach using Keras, Pytorch, and TensorFlow. Everyone seems to have their own opinion on the loss function. Some just take MSE for width and height estimation, and the rest with BCE, some take x,y,w,h with MSE and the rest with BCE.
Here's some of my code:
loss_x = self.mse_loss(x[mask], tx[mask])
loss_y = self.mse_loss(y[mask], ty[mask])
loss_w = self.mse_loss(w[mask], tw[mask])
loss_h = self.mse_loss(h[mask], th[mask])
loss_conf = self.bce_loss(pred_conf[conf_mask_false], tconf[conf_mask_false]) + self.bce_loss(pred_conf[conf_mask_true],tconf[conf_mask_true])
loss_cls = (1 / nB) * self.ce_loss(pred_cls[mask],torch.argmax(tcls[mask], 1))
loss = loss_x + loss_y + loss_w + loss_h + loss_conf + loss_cls
As the loss function plays an important role in the training. I wish someone could help me to figure it out.
Upvotes: 5
Views: 9574
Reputation: 4151
Loss function of Yolo v3, look at src/yolo_layer.c
delta for box, line 93
float delta_yolo_box(box truth, float *x, float *biases, int n, int index, int i, int j, int lw, int lh, int w, int h, float *delta, float scale, int stride)
{
box pred = get_yolo_box(x, biases, n, index, i, j, lw, lh, w, h, stride);
float iou = box_iou(pred, truth);
float tx = (truth.x*lw - i);
float ty = (truth.y*lh - j);
float tw = log(truth.w*w / biases[2*n]);
float th = log(truth.h*h / biases[2*n + 1]);
delta[index + 0*stride] = scale * (tx - x[index + 0*stride]);
delta[index + 1*stride] = scale * (ty - x[index + 1*stride]);
delta[index + 2*stride] = scale * (tw - x[index + 2*stride]);
delta[index + 3*stride] = scale * (th - x[index + 3*stride]);
return iou;
}
delta for class, line 111
void delta_yolo_class(float *output, float *delta, int index, int class, int classes, int stride, float *avg_cat)
{
int n;
if (delta[index]){
delta[index + stride*class] = 1 - output[index + stride*class];
if(avg_cat) *avg_cat += output[index + stride*class];
return;
}
for(n = 0; n < classes; ++n){
delta[index + stride*n] = ((n == class)?1 : 0) - output[index + stride*n];
if(n == class && avg_cat) *avg_cat += output[index + stride*n];
}
}
delta for objectness, line 178
l.delta[obj_index] = 0 - l.output[obj_index];
if (best_iou > l.ignore_thresh) {
l.delta[obj_index] = 0;
and
l.delta[obj_index] = 1 - l.output[obj_index];
Loss = sum of square
*(l.cost) = pow(mag_array(l.delta, l.outputs * l.batch), 2);
Anyway I just give you a glimpse about loss function in Yolo V3. For detail explanation you should follow this github discussion :
https://github.com/AlexeyAB/darknet/issues/1695#issuecomment-426016524
and
https://github.com/AlexeyAB/darknet/issues/1845#issuecomment-434079752
Upvotes: 3