R-CNN全称为 Region-CNN,它是第一个成功地将深度学习应用到目标检测的算法,后续的改进算法 Fast R-CNN、Faster R-CNN都是基于该算法。
传统方法 VS R-CNN
传统的目标检测大多以图像识别为基础。一般是在图片上穷举出所有物体可能出现的区域框,然后对该区域框进行特征提取,运用图像识别方法进行分类,最后通过非极大值抑制输出结果。
传统方法最大的问题在特征提取部分,它基于经验驱动的人造特征范式,如haar、HOG、SIFT,并不能很好的表征样本。
R-CNN思路大致相同,但是采用了深度网络来提取特征。
计算机视觉概念科普
在计算机视觉领域,有很多不同方向的任务,如图像分类、图像定位、目标检测、实例分割
R-CNN可以用于后三种。
R-CNN详解
R-CNN模型比较复杂,训练和测试过程分开讲解
训练过程
训练过程的特点在于采用了有监督预训练,在特定样本上微调
1. 有监督预训练
样本 | 来源 |
---|---|
正样本 | ILSVRC2012 |
负样本 | ILSVRC2012 |
ILSVRC数据集样本很多;
ILSVRC数据集只有图像类别标签,没有图像中物体位置标签;
采用AlexNet网络进行有监督预训练,学习率0.01;
AlexNet 输入为227x227,输出为4096-->1000
这一步的目的是得到预训练参数
================ 扩展 ================
什么叫有监督预训练
有监督预训练也叫迁移学习,举个例子,现在有大量人脸图片,其类别标签为年龄,可以根据该训练集得到CNN网络,用于预测年龄;现在又有一批人脸数据,其类别标签为性别,我们是否需要从头训练一个CNN网络呢?不需要。
我们可以把“年龄网络”的最后一层或几层去掉,换上我们需要的“性别网络”,把“年龄网络”前些层的参数直接赋给“性别网络”对应层,作为这些层的初始化参数,“性别网络”新增层采用常规初始化参数,然后利用训练集重新训练该网络。
说的简单一点,把一个训练好的模型的参数直接用于另一个模型,作为这个模型的初始化参数,再进行训练
有监督预训练的作用
1. 实践证明,提高了模型的精度
2. 加快模型的训练速度
3. 解决了小样本数据集无法训练深层CNN网络的问题,也解决了小样本数据集容易过拟合的问题
2. 特定样本下的微调
样本 | 来源 |
---|---|
正样本 | Ground Truth+与Ground Truth相交IoU>0.5的建议框【由于Ground Truth太少了】 |
负样本 | 与Ground Truth相交IoU≤0.5的建议框 |
PASCAL VOC 2007数据集样本较少;
PASCAL VOC 2007数据集既有图像类别标签,也有图像中物体位置标签;
采用训练好的 AlexNet 网络进行PASCAL VOC 2007数据集下的微调,学习率0.001,;【参数已经预训练,所以学习率要小一点】
mini-batch 采用32正样本96负样本;【由于正样本比较少】
该网络的输入为通过 Selective Search 得到的建议框,需要变形为227x227,输出层由1000改为21,输出21类【20类+背景】
这一步的目的是得到用于特征提取的参数
================ 扩展 ================
为什么要在特定样本下微调?或者说可不可以直接用AlexNet的参数进行特征提取?
作者对微调与不微调都进行了实验
不微调,直接拿AlexNet的pool5、fc6、fc7层参数分别进行特征提取,输入SVM进行训练,【这相当于把AlexNet当做特征提取的标准模板,万金油模板,意思是不管什么任务,就是这一套,就像传统的harr特征一样】
结果发现 fc6层提取的特征比fc7更准,pool5层提取的特征与fc6、fc7层准确率差不多;
微调,用微调后的pool5、fc6、fc7层参数分别进行特征提取,发现fc6、fc7层提取的特征准确率明显高于pool5层;
卷积与全连接
通过上述实验,可以得出如下结论,
卷积提取的是共性特征,或者说基础特征,如人脸的鼻子、眼睛等;【注意鼻子眼睛只是举例,方便你理解,实际上不是的,可能只是一个点,比如你的色斑,只是形象描述而已】
全连接是针对类别标签得到的个性特征,如欧洲人鼻子比较尖,眼睛比较蓝;
3. SVM训练
样本 | 来源 |
---|---|
正样本 | Ground Truth |
负样本 | 与Ground Truth相交IoU<0.3的建议框 |
SVM是二分类器,故需要多个SVM分类器 ;
SVM输入是微调后的AlexNet参数提取的特征,4096维,输出每类的得分;
负样本太多,采用hard negative mining的方法在负样本中选取有代表性的负样本
这一步的目的是得到SVM分类器
================ 扩展 ================
什么叫 IoU
图片的交集/图片的并集,A∩B/AUB
为什么要IoU
通过某种方式选择图片上物体所在区域时,可能会有同一个物体被多次选择的情况,此时需要通过IoU识别。
为什么第2步微调模型时正负样本IoU阈值与第3步SVM不一样?0.5 VS 0.3
1. 微调阶段由于CNN很容易对小样本过拟合,所以需要增加正样本的数目,而负样本不需增加,因为负样本是在图片上搜索到的,想要多少有多少,为了得到更多正样本,就要降低IoU的阈值,一般我们认为两张图片重合70% 80%才算一张,而降低到50%就能增加正样本。
而SVM不需要太多的数据集,无需增加样本,故IoU限制比较严格,重合70%才认为是一张图片。
2. 微调阶段是为了获取特征提取的参数,而样本中人脸有可能是半张脸,或者有遮挡等等,如果CNN模型只能提取整张脸的特征,那“部分脸”肯定会识别错误,减小阈值可以得到很多“部分脸”的样本,从而CNN可以提取“部分脸”的特征,原则上讲,如果计算资源运行,我们希望特征越多越好,即使无用也没关系。
而SVM是分类器,根据输入特征进行分类,正负样本需要有比较明显的界线,最好不要有模棱两可的样本,故 IoU要严格限制。
为什么不用AlexNet直接分类,而是又训练了SVM?
这个问题其实挺不好回答的,
网上有这么说的:因为 AlexNet 和 SVM 采用的正负样本不同,微调阶段正样本不一定是正样本,而SVM正样本就是正样本,而且微调阶段负样本随机采样,而SVM采用hard negative mining方法筛选负样本,
那不禁有人要问了,AlexNet 也采用 真正的正样本,负样本也hard negative mining方法筛选,不就行了?
我觉得这是一个需要系统回答的问题,个人理解如下:
传统的图像识别、目标检测等采用人造特征进行特征提取,深度学习盛行以后,作者想采用深度学习来提取特征,注意初衷只是提取特征,然后用传统机器学习如 SVM等来进行分类,以便比较人造特征和深度学习提取特征的差别有多大,所以作者刚开始就打算要SVM,而在实验过程中,作者发现了样本小,部分脸等问题,所以采用了微调阶段的数据增强等措施,而SVM就是正常的模型训练。
4. Bounding-Box Regression
样本 | 来源 |
---|---|
正样本 | 与Ground Truth相交IoU最大的Region Proposal,并且IoU>0.6的Region Proposal |
回归器训练,这是在干嘛,哪来的回归问题?
首先要明确目标检测不仅是图像识别,还需要对物体进行定位,Bounding-Box定位准确与否也是模型精度的一部分。这里定位准确率可以用IoU衡量。
如上图,即使图像识别为飞机,但是标注框不准,IoU<0.5,也相当于没有检测出目标。
这一步的目的是生成标注框
================ 扩展 ================
回归模型如何设计
上图中,红色框P代表 Selective Search 选择的建议框Region Proposal,绿色框G代表实际框Ground Truth,蓝色框G'代表Region Proposal进行回归后的预测窗口
目标是找到P到G’的线性变换,使得G’无限接近于G。【笔者认为IoU>0.6的建议框才符合线性变换】
思考下线性变换,初始化参数wx+b,真实值y,然后 y-(wx+b),使其最小,思路同上。
设 P=(Px, Py, Pw, Ph),分别代表P的横坐标,纵坐标,红色框的宽度,高度,(Px, Py)是红色框的中心;
G=(Gx, Gy, Gw, Gh),绿色框,
G'=(G'x, G'y, G'w, G'h),蓝色框,
类比线性回归 wP+b-G=G'-G
从P到G',其实是一个平移和缩放的过程,
平移可以表示为
G'x=Px+Δx
G'y=Py+Δy
缩放可以表示为
G'w=Pw*Δw
G'h=Ph*Δh
作者用下面的式子表示线性变换
d(P)的输入其实并不是一个(x,y,w,h),而是 AlexNet 网络pool5层的特征 Ø(P)的线性变换,即 d(P)=wØ(P),w就是回归参数,
把真实数据带入上述线性变换的公式,即把G'换成G
上面的d是预测,t是实际,t-d就是误差,于是得到损失函数
后面为正则项,不再赘述。
稍微总结一下
a. 构造样本对,也就是回归的数据集
// 首先明白一点,bbr是根据每类样本的特征得到回归方程的,所以每个类别有一个回归方程
// 每类样本中每次识别都选择与Ground Truth IoU最大的建议框,并且IoU>0.6,作为一个样本{P,G}
b. 针对每个类别训练回归器,输入该类别的样本,以及每个P对应的AlexNet的pool5层的特征
c. 得到参数w
至此,R-CNN 训练完成。
测试过程
1. 给定一张多目标图片,采用 Selective Search 选出约2000个建议框
// 在每个建议框周围加上16个 <像素值为建议框像素平均值> 的边框,再形变为 227x227 的大小
// 将所有建议框像素减去 该建议框的像素平均值
2. 将2000个建议框送入AlexNet网络进行特征提取,生成2000x4096矩阵
3. 将特征矩阵送入SVM模型,生成2000x20矩阵,表示每个建议框输入每个类别的得分
4. 对上述2000x20矩阵每一列即每一类进行 非极大值抑制 操作,剔除重复建议框,得到每列中得分最高的不同建议框
5. 对每列中剩下的建议框进行回归操作,得到标注框
================ 扩展 ================
Selective Search
分割图片,具体我会在其他博客详解
如何形变为227x227
先解释两个名词
各向异性缩放:非等比例缩放,不管图片的长宽比例,不管缩放后是否扭曲,直接缩放就是了;缩放后一般会扭曲,扭曲会对CNN有一定影响
各向同性缩放:有两种做法
1. 直接在原始图片中,把bounding box的边界进行扩展延伸成正方形,然后再进行裁剪;如果已经延伸到了原始图片的外边界,那么就用bounding box中的颜色均值填充;
2. 先把bounding box图片裁剪出来,然后用固定的背景颜色填充成正方形图片(背景颜色也是采用bounding box的像素颜色均值);
作者进行了如下尝试
① 考虑context【图像中context指RoI周边像素】的各向同性变形,建议框像周围像素扩充到227×227,若遇到图像边界则用建议框像素均值填充,下图第二列;
② 不考虑context的各向同性变形,直接用建议框像素均值填充至227×227,下图第三列;
③ 各向异性变形,简单粗暴对图像就行缩放至227×227,下图第四列;
④ 变形前先进行边界像素填充【padding】处理,即向外扩展建议框边界,以上三种方法中分别采用padding=0下图第一行,padding=16下图第二行进行处理;
经过作者一系列实验表明采用padding=16的各向异性变形即下图第二行第三列效果最好,能使mAP提升3-5%。
非极大值抑制
解决问题:多个建议框指向了同一个物体,我们只需要该物体IoU最大的建议框
具体操作
1. 输入为2000x20矩阵,2000代表2000个建议框,20代表20个类别
2. 对每个类别进行排序,从大到小
3. 首先取得分最高的建议框,设为物体1,然后遍历后面所有的建议框,如果建议框和物体1的建议框IoU大于阈值,则认为是一个物体,把这些建议框删除,
如果小于阈值,则认为是另一个物体,暂时保留,保留下来的建议框仍然是有序的
4. 去掉该列被认定的建议框,如物体1,将剩下的建议框进行步骤3操作,直到认定完所有物体
5. 对每列进行上述操作
6. 也可以设定阈值对每列中剩余建议框与真实标注IoU较小的建议框【作者没有此步】
至此,R-CNN 测试完成。
R-CNN 的问题
1. 处理速度慢,一张图片采用 Selective Search 获取2000个建议框,然后变形,通过AlexNet提取特征,计算量很大,而且存在多个重复区域的重复计算
2. 整体过程太复杂,计算量大,一句话就够了
参考资料:
https://blog.csdn.net/wopawn/article/details/52133338
https://blog.csdn.net/qq_35608277/article/details/80178628
https://blog.csdn.net/v1_vivian/article/details/80292569 Bounding-Box 回归
https://blog.csdn.net/zijin0802034/article/details/77685438 Bounding-Box 回归
https://github.com/Stick-To/LH-RCNN-tensorflow/blob/master/LH_RCNN.py github 代码