\begin{align}
&\lambda_{coord} \sum_{i=0}^{S^2}\sum_{j=0}^B \mathbb{1}_{ij}^{obj}[(x_i-\hat{x}_i)^2 + (y_i-\hat{y}_i)^2 ] \\&+ \lambda_{coord} \sum_{i=0}^{S^2}\sum_{j=0}^B \mathbb{1}_{ij}^{obj}[(\sqrt{w_i}-\sqrt{\hat{w}_i})^2 +(\sqrt{h_i}-\sqrt{\hat{h}_i})^2 ]\\
&+ \sum_{i=0}^{S^2}\sum_{j=0}^B \mathbb{1}_{ij}^{obj}(C_i - \hat{C}_i)^2 + \lambda_{noobj}\sum_{i=0}^{S^2}\sum_{j=0}^B \mathbb{1}_{ij}^{noobj}(C_i - \hat{C}_i)^2 \\
&+ \sum_{i=0}^{S^2} \mathbb{1}_{i}^{obj}\sum_{c \in classes}(p_i(c) - \hat{p}_i(c))^2 \\
\end{align}
Doesn't the YOLOv2 Loss function looks scary? It's not actually! It is one of the boldest, smartest loss function around.
Let's first look at what the network actually predicts.
If we recap, YOLOv2 predicts detections on a 13x13 feature map, so in total, we have 169 maps/cells.
We have 5 anchor boxes. For each anchor box we need Objectness-Confidence Score (whether any object was found?), 4 Coordinates ($t_x, t_y, t_w,$ and $t_h$) for the anchor box, and 20 top classes. This can crudely be seen as 20 coordinates, 5 confidence scores, and 100 class probabilities for all 5 anchor box predictions put together.
We have few things to worry about:
- $x_i, y_i$, which is the location of the centroid of the anchor box
- $w_i, h_i$, which is the width and height of the anchor box
- $C_i$, which is the Objectness, i.e. confidence score of whether there is an object or not, and
- $p_i(c)$, which is the classification loss.
- We not only need to train the network to detect an object if there is an object in a cell, we also need to punish the network, it if predicts an object in a cell, when there wasn't any. How do we do this? We use a mask ($𝟙_{i}^{obj}$ and $𝟙_{i}^{noobj}$) for each cell. If originally there was an object $𝟙_{i}^{obj}$ is 1 and other no-object cells are 0. $𝟙_{i}^{noobj}$ is just inverse of $𝟙_{i}^{obj}$, where it is 1 if there was no object in the cell and 0 if there was.
- We need to do this for all 169 cells, and
- We need to do this 5 times (for each anchor box).
All losses are mean-squared errors, except classification loss, which uses cross-entropy function.
Now, let's break the code in the image.
We need to compute losses for each Anchor Box (5 in total)
- $\sum_{j=0}^B$ represents this part, where B = 4 (5 - 1, since the index starts from 0)
We need to do this for each of the 13x13 cells where S = 12 (since we start index from 0)
- $\sum_{i=0}^{S^2}$ represents this part.
$𝟙_{ij}^{obj}$ is 1 when there is an object in the cell $i$, else 0.
$𝟙_{ij}^{noobj}$ is 1 when there is no object in the cell $i$, else 0.
$𝟙_{i}^{obj}$ is 1 when there is a particular class is predicted, else 0.
λs are constants. λ is highest for coordinates in order to focus more on detection (remember, in YOLOv2, we first train it for recognition and then for detection, penalizing heavily for recognition is waste of time, rather we focus on getting best bounding boxes!)
We can also notice that $w_i, h_i$ are under square-root. This is done to penalize the smaller bounding boxes as we need better prediction on smaller objects than on bigger objects (author's call). Check out the table below and observe how the smaller values are punished more if we follow "square-root" method (look at the inflection point when we have 0.3 and 0.2 as the input values) (PS: I have kept the ratio of var1 and var2 same just for explanation):
var1 | var2 | (var1 - var2)^2 | (sqrtvar1 - sqrtvar2)^2
0.0300 | 0.020 | 9.99e-05 | 0.001
0.0330 | 0.022 | 0.00012 | 0.0011
0.0693 | 0.046 | 0.000533 | 0.00233
0.2148 | 0.143 | 0.00512 | 0.00723
0.3030 | 0.202 | 0.01 | 0.01
0.8808 | 0.587 | 0.0862 | 0.0296
4.4920 | 2.994 | 2.2421 | 0.1512
Not that scary, right!
Read HERE for further details.