3-5 Bounding Box 预测
Bounding Box 预测(Bounding box predictions)
滑动窗口法的卷积实现虽然效率更高,但仍然存在问题,不能输出最精准的边界框。
在滑动窗口法中,你取这些离散的位置集合,然后在它们上运行分类器,在这种情况下,这些边界框没有一个能完美匹配汽车位置。
其中一个能得到更精准边界框的算法是 YOLO 算法, YOLO(You only look once)意思是你只看一次。
比如你的输入图像是 100×100 的,然后在图像上放一个3×3网格,实际实现时会用更精细的网格,可能是 19×19。基本思路是使用图像分类和定位算法,逐一应用在图像的 9 个格子中。更具体一点,你需要这样定义训练标签,所以对于 9 个格子中的每一个指定一个标签y,y是 8 维的:
${p_c}$等于 0 或 1 取决于这个绿色格子中是否有图像。然后${b_x}$, ${b_y}$, ${b_h}$ ,${b_w}$作用就是,如果那个格子里有对象,那么就给出边界框坐标。${c_1}$,${c_2}$,${c_3}$就是你想要识别的三个类别,背景类别不算,所以你尝试在背景类别中识别行人、汽车和摩托车,那么${c_1}$,${c_2}$,${c_3}$可以是行人、汽车和摩托车类别。这张图里有 9 个格子,所以对于每个格子都有这么一个向量。
这张图有两个对象,YOLO 算法做的就是,取两个对象的中点,然后将这个对象分配给包含对象中点的格子。所以左边的汽车就分配到绿色框标记的格子上,右边的汽车就分配到黄色框标记的格子上。即使中心格子同时有两辆车的一部分,我们就假装中心格子没有任何我们感兴趣的对象。所以对于中心格子,分类标签y和这个没有对象的向量类似:
绿色框和黄色框的格子目标标签应该是这样的:
所以对于这里 9 个格子中任何一个,你都会得到一个 8 维输出向量,因为这里是 3×3 的网格,所以有 9 个格子,总的输出尺寸是 3×3×8,所以目标输出是 3×3×8。
对于这个例子中,左上格子是 1×1×8,对应的是 9 个格子中左上格子的输出向量。所以总的目标输出标签尺寸就是 3×3×8:
如果你现在要训练一个输入为 100×100×3 的神经网络,现在这是输入图像,然后你有一个普通的卷积网络,卷积层,最大池化层等等,最后你会有这个,选择卷积层和最大池化层,这样最后就映射到一个 3×3×8 输出尺寸。所以你要做的是,有一个输入x,就是这样的输入图像,然后你有这些 3×3×8 的目标标签y。当你用反向传播训练神经网络时,将任意输入x映射到这类输出向量y。
所以这个算法的优点在于神经网络可以输出精确的边界框,所以测试的时候,你做的是喂入输入图像x,然后跑正向传播,直到你得到这个输出y。然后对于这里 3×3 位置对应的 9个输出,就可以知道9个位置之一是否有对象,对象类型是什么。只要每个格子中对象数目没有超过 1 个,这个算法应该是没问题的。实践中你可能会使用更精细的 19×19 网格,所以输出就是 19×19×8。这样的网格精细得多,那么多个对象分配到同一个格子得概率就小得多。
把对象分配到一个格子的过程是,你观察对象的中点,然后将这个对象分配到其中点所在的格子,所以即使对象可以横跨多个格子,也只会被分配到 9 个格子其中之一,就是 3×3 网络的其中一个格子,或者 19×19 网络的其中一个格子。在 19×19 网格中,两个对象的中点处于同一个格子的概率就会更低。
它显式地输出边界框坐标,所以这能让神经网络输出边界框,可以具有任意宽高比,并且能输出更精确的坐标,不会受到滑动窗口分类器的步长大小限制。其次,这是一个卷积实现,你并没有在 3×3 网格上跑 9 次算法,或者,如果你用的是 19×19 的网格, 19 平方是 361 次,所以你不需要让同一个算法跑 361 次。相反,这是单次卷积实现,但你使用了一个卷积网络,有很多共享计算步骤,在处理这 3×3 计算中很多计算步骤是共享的,或者你的 19×19 的网格,所以这个算法效率很高。
事实上 YOLO 算法有一个好处,也是它受欢迎的原因,因为这是一个卷积实现,实际上它的运行速度非常快,可以达到实时识别。
在 YOLO 算法中,对于这个方框,我们约定左上这个点是(0,0),然后右下这个点是(1,1),要指定橙色中点的位置,${b_x}$大概是 0.4,${b_y}$大概是 0.3。然后边界框的高度用格子总体宽度的比例表示,所以这个红框的宽度可能是蓝线的 90%,所以${b_h}$是 0.9,它的高度也许是格子总体高度的一半,这样的话${b_w}$就是 0.5。换句话说,${b_x}$,${b_y}$,${b_h}$,${b_w}$单位是相对于格子尺寸的比例,所以${b_x}$,${b_y}$必须在 0 和 1 之间。如果它不在 0 和 1 之间,如果它在方块外,那么这个对象就应该分配到另一个格子上。