不知不觉已是第七篇了,发觉这篇论文所涉及的知识点特别多,我的个人习惯是先把论文看一遍,了解这个大概,然后将源码运行一遍,熟悉下这个模型带来的大概效果是怎么样的,然后就阅读源码了,从源码中发现很多知识点,然后就自己做个梳理。由于标题不能太长,所以使用了统一标题加数字来处理。
当然对于看论文,可以先看Fast R-CNN,看完之后再看Faster R-CNN也可以。论文是基础,对模型整体的把握以及跟以前的模型对比有什么优势。
我这里整理下前面6篇,每篇大概讲解的是什么内容,方便大家查阅:
MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《1》:论文源地址,克隆MXNet版本的源码,安装环境与测试,以及对下载的源码的每个目录做什么用的,做个解释。
MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《2》:对论文中的区域提议、平移不变锚、多尺度预测等概念的了解,对损失函数、边界框回归的公式的了解,以及共享特征的训练网络的方法。
MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《3》:加载模型参数,对参数文件的了解,以及感兴趣区域ROI和泛洪填充的方法(FLOODFILL_FIXED_RANGE,FLOODFILL_MASK_ONLY)
MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《4》:下载与熟悉Pascal VOC2007,2012语义分割数据集,明白实例分割除了分类之外,还可以细分到像素级别的所属类别。
MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《5》:主要就是熟悉转置卷积与大家所熟知的卷积有什么区别,作用是什么,以及双线性插值等相关知识
MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《6》:主要讲解关于参数解析的安全执行(ast.literal_eval),ROI池化以及计算图的可视化的处理
打印方式
通过前面的学习,应该对Faster R-CNN有了一定的了解了,这篇文章我们从训练模型开始,看有哪些知识点需要去学习的。
python train.py --dataset voc --network vgg16 --pretrained model/vgg16-0000.params
训练的数据集是VOC,网络选择VGG16,预处理模型参数文件vgg16-0000.params,其中加载参数文件,打印内容的方式有三种:
遍历
import mxnet as mx
mydict=mx.nd.load('model/vgg16-0000.params')
for k,v in mydict.items():tp,name=k.split(":")print(tp,name,end=',')
这种就是遍历参数文件,然后print,另一种就是pprint,就是pretty print漂亮打印,打印的时候不是一行输出,而是多行输出,对于调试的时候,需要打印比较长的数据的时候,这个打印看起来就舒服很多了。
pprint漂亮打印
import pprint
print('参数文件内容如下:\n{}'.format(pprint.pformat(mydict)))
logging日志
还可以使用日志的方式,指定文件名的话,内容就会保存在日志文件中。当然一般来说日志的作用是作为后期出现故障等调试时做辅助用。
import logging
logging.basicConfig(filename='output.log',datefmt='%Y/%m/%d %H:%M:%S',format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logger = logging.getLogger(__name__)
logger.info('参数文件内容如下:\n{}'.format(pprint.pformat(mydict)))
奇异值分解SVD
属于线性代数的知识,在以前的文章有讲过:线性代数的相关计算(numpy)(主要讲解了逆矩阵np.linalg.inv(M)[M必须是方阵]、广义的逆矩阵np.linalg.pinv(M)、解范数值、解特征值和特征向量等相关知识)
这里在Fast R-CNN论文中出现,所以再次复习一遍,它在我们的深度学习有哪些具体作用。
首先了解下什么是奇异值(来自百度百科):奇异值是矩阵里的概念,一般通过奇异值分解定理求得。设A为m*n阶矩阵,q=min(m,n),A*A的q个非负特征值的算术平方根叫作A的奇异值。奇异值分解是线性代数和矩阵论中一种重要的矩阵分解法,适用于信号处理和统计学等领域
奇异值分解(Singular Value Decomposition)是在机器学习领域广泛应用的算法,主要应用如下:
信息检索(LSA:Implicit semantic analysis隐性语义索引,LSA:Implicit semantic analysis隐性语义分析),分解后的奇异值代表了文章的主题或者概念
数据压缩:通过奇异值分解,选择能量较大的前N个奇异值来代替所有的数据信息,这个看N的实际情况取值。
我们来看具体的实例吧,这些都来自np.linalg模块里的方法
import numpy as npD=np.mat("1 0 -1;-2 1 4")
u,sigma,v=np.linalg.svd(D,full_matrices=False)
'''
matrix([[-0.27794882, 0.96059588],[ 0.96059588, 0.27794882]])
array([4.76823893, 0.51370952])
matrix([[-0.46120604, 0.20145716, 0.86412036],[ 0.78779586, 0.54106224, 0.29432861]])
'''
u1=np.transpose(u)#转置
v1=np.transpose(v)#转置
np.round(np.dot(u,u1)).astype(np.int)#这里需要注意的是,先四舍五入再取整数
np.round(np.dot(v,v1)).astype(np.int)
'''
matrix([[1, 0],[0, 1]])
'''
它们的返回值都是单位矩阵(也就是u*u1(u的转置),v*v1(v的转置)是一个单位矩阵),所以这里的u和v是正交矩阵,也分别是它们的特征向量,也叫做左奇异向量与右奇异向量。
sigma=np.diag(sigma)
'''
array([[4.76823893, 0. ],[0. , 0.51370952]])
'''
对角线矩阵,对角线的值就是奇异值。这个np.diag的用法就是获取对角线的值,如果是向量就转换成对角线矩阵。
然后我们验证下,三个矩阵相乘:
np.round(u*sigma*v)
'''
matrix([[ 1., 0., -1.],[-2., 1., 4.]])
'''
那可能有伙伴们会问,这个乘法和dot点积不是不一样吗?怎么结果一样了,这里需要注意的是,乘法运算的类型是matrix矩阵类型,跟ndarray类型有区别。
那为什么可以降噪,我们在这里看个具体的示例:
每行表示一个用户,数字表示对电影的评分。
M=np.mat("9 8.8 3 7;5 6 6.4 7.7;8.2 4 3.9 9.2;2.5 8.8 5.2 7.7;6.6 5.8 7 7.4;8 6.4 6 7.1")
U,Sigma,V=np.linalg.svd(M)
Sigma=np.diag(Sigma)
前面说了保留前N个奇异值,这个我们取N=2来看下,因为观察我们发现奇异值是从大到小排列的,这个时候应该明白取前面基本上可以覆盖绝大部分的特征的原因了吧:
U=U[:,:2]
Sigma=Sigma[:2,:2]
V=V[:2,:]
>>> U*Sigma*V
matrix([[8.44657466, 6.35754808, 5.06705626, 8.18814074],
[5.18246049, 6.99714537, 5.44187044, 7.33048151],
[8.90652435, 5.11636121, 4.14699678, 7.45154724],
[2.64602817, 8.28371505, 6.32800459, 7.25218233],
[6.51865687, 6.8033864 , 5.3397199 , 7.73227643],
[7.68512295, 6.44491283, 5.10790042, 7.94200016]])
>>> M
matrix([[9. , 8.8, 3. , 7. ],
[5. , 6. , 6.4, 7.7],
[8.2, 4. , 3.9, 9.2],
[2.5, 8.8, 5.2, 7.7],
[6.6, 5.8, 7. , 7.4],
[8. , 6.4, 6. , 7.1]])
这个截取的SVD跟M比较,它们各自的值还是比较接近的,当然这个取决于N的值,大点就更准确,在这里你取N=3试下效果就明白了,也就是说可以使用取前N个奇异值来代替全部信息,这就起到了压缩数据的作用,比如图像压缩等,反过来可以对图像降噪,那些噪点的奇异值很小,直接取0,这样就起到降噪的效果了。
截取SVD换句话说就将大矩阵简化成三个小矩阵来计算,可以大大减少计算量。